請生成 一個互動射擊遊戲
Last edited by @suen 2025-06-12T10:35:14Z
請生成 一個互動射擊遊戲
Last edited by @suen 2025-06-12T10:35:14Z
好的,我很樂意為您生成一個互動射擊遊戲。
為了確保我能創建出您想要的遊戲,請您提供更多細節:
請盡可能詳細地描述您心中的遊戲,這樣我才能更好地為您構建它。
你隨意,復古點即可
好的,既然您想要一個復古風格的互動射擊遊戲,我將為您設計一個經典的固定螢幕射擊遊戲,類似於早期街機遊戲的風格。
遊戲概念:
您將控制一個位於螢幕底部中央的炮台,左右移動來瞄準。螢幕上方會不斷有簡單的幾何形狀敵人出現並向下移動。您的目標是射擊並摧毀這些敵人,以獲得分數,同時避免敵人到達螢幕底部。您將有有限的生命值,當生命值歸零時,遊戲結束。
我將會遵循以下步驟來為您創建:
現在,讓我來創建這個遊戲的初始版本。
<div id="app">
<div id="game-container">
<canvas id="gameCanvas" width="600" height="800"></canvas>
<div id="ui">
<span id="score-label">SCORE: </span><span id="score-display">0</span>
<span id="lives-label">LIVES: </span><span id="lives-display">3</span>
</div>
<div id="game-over-screen">
<p>GAME OVER!</p>
<p id="final-score">SCORE: 0</p>
<button id="restart-button">RESTART</button>
</div>
</div>
</div>
#app {
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
background-color: #1a1a1a; /* Dark background */
overflow: hidden;
font-family: 'Courier New', Courier, monospace; /* Retro-style font */
color: #0f0; /* Retro green text */
text-shadow: 0 0 5px #0f0; /* Subtle glow for retro feel */
font-size: 1.2em;
user-select: none; /* Prevent text selection */
}
#game-container {
position: relative;
width: clamp(300px, 90vw, 600px); /* Responsive width, max 600px */
padding-bottom: 133.33%; /* Maintain 3:4 aspect ratio (width:height = 600:800) */
height: 0;
overflow: hidden; /* Hide anything outside */
border: 3px solid #0f0; /* Retro border */
box-shadow: 0 0 15px rgba(0, 255, 0, 0.7); /* Green glow effect */
}
#gameCanvas {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: block;
background-color: #000000; /* Game background */
image-rendering: crisp-edges; /* For pixel art look */
image-rendering: pixelated; /* Standard for pixel art */
}
#ui {
position: absolute;
top: 10px;
left: 10px;
right: 10px;
display: flex;
justify-content: space-between;
z-index: 10;
pointer-events: none; /* Allow mouse events to pass through to canvas */
}
#score-display,
#lives-display {
font-weight: bold;
color: #0f0;
}
#game-over-screen {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.8); /* Semi-transparent overlay */
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
z-index: 20;
text-align: center;
color: #0f0;
font-size: 2em;
display: none; /* Hidden by default */
}
#game-over-screen p {
margin: 10px 0;
text-shadow: 0 0 10px #0f0;
}
#restart-button {
background-color: #0f0;
color: #000;
border: 2px solid #000;
padding: 10px 20px;
font-family: 'Courier New', Courier, monospace;
font-size: 1.5em;
cursor: pointer;
box-shadow: 0 0 8px rgba(0, 255, 0, 0.7);
transition: background-color 0.1s, color 0.1s;
text-shadow: none; /* Remove text shadow for button text */
}
#restart-button:hover {
background-color: #000;
color: #0f0;
border-color: #0f0;
}
document.addEventListener('DOMContentLoaded', () => {
const canvas = document.getElementById('gameCanvas');
const ctx = canvas.getContext('2d');
const scoreDisplay = document.getElementById('score-display');
const livesDisplay = document.getElementById('lives-display');
const gameOverScreen = document.getElementById('game-over-screen');
const finalScoreDisplay = document.getElementById('final-score');
const restartButton = document.getElementById('restart-button');
// Game Constants (Internal Resolution)
const CANVAS_WIDTH = 600;
const CANVAS_HEIGHT = 800;
// Set canvas internal resolution
canvas.width = CANVAS_WIDTH;
canvas.height = CANVAS_HEIGHT;
// Game State
let score = 0;
let lives = 3;
let gameRunning = false;
let isGameOver = false;
// Player
const player = {
width: 60,
height: 20,
x: CANVAS_WIDTH / 2 - 30,
y: CANVAS_HEIGHT - 40,
speed: 8,
color: '#00ff00', // Green
flashing: false,
flashTimer: 0,
flashDuration: 500 // ms
};
// Projectiles
const projectiles = [];
const PROJECTILE_WIDTH = 4;
const PROJECTILE_HEIGHT = 15;
const PROJECTILE_SPEED = 10;
const PROJECTILE_COOLDOWN = 200; // ms
let lastShotTime = 0;
// Targets
const targets = [];
const INITIAL_TARGET_SPEED = 1.5;
let targetSpeed = INITIAL_TARGET_SPEED;
const TARGET_SPAWN_INTERVAL = 1000; // ms
let lastTargetSpawnTime = 0;
const TARGET_SPEED_INCREASE_RATE = 0.00005; // speed increase per ms
// Explosions (for hit effects)
const explosions = [];
const EXPLOSION_DURATION = 300; // ms
// Input State
const keysPressed = {};
let mouseX = CANVAS_WIDTH / 2; // Default mouse X to center
let mouseIsDown = false;
// Game Loop Variables
let lastTime = 0;
let animationFrameId;
// --- Helper Functions ---
function randomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
function getRandomColor() {
const colors = ['#ff0000', '#0000ff', '#ffff00', '#ff00ff', '#00ffff']; // Red, Blue, Yellow, Magenta, Cyan
return colors[randomInt(0, colors.length - 1)];
}
function checkCollision(rect1, rect2) {
return rect1.x < rect2.x + rect2.width &&
rect1.x + rect1.width > rect2.x &&
rect1.y < rect2.y + rect2.height &&
rect1.y + rect1.height > rect2.y;
}
function createTarget() {
const type = randomInt(0, 2); // 0: square, 1: triangle, 2: circle
const size = randomInt(20, 50);
const x = randomInt(size / 2, CANVAS_WIDTH - size / 2);
const y = -size; // Start above the canvas
const color = getRandomColor();
targets.push({
x: x,
y: y,
width: size,
height: size,
color: color,
type: type,
speed: targetSpeed,
rotation: 0 // For triangles/circles if needed, though not strictly required for simple shapes.
});
}
function playerLoseLife() {
lives--;
livesDisplay.textContent = lives;
player.flashing = true;
player.flashTimer = 0;
if (lives <= 0) {
endGame();
}
}
function endGame() {
isGameOver = true;
gameRunning = false;
cancelAnimationFrame(animationFrameId);
finalScoreDisplay.textContent = `SCORE: ${score}`;
gameOverScreen.style.display = 'flex';
}
function resetGame() {
score = 0;
lives = 3;
player.x = CANVAS_WIDTH / 2 - player.width / 2;
projectiles.length = 0;
targets.length = 0;
explosions.length = 0;
targetSpeed = INITIAL_TARGET_SPEED;
lastShotTime = 0;
lastTargetSpawnTime = 0;
player.flashing = false;
player.flashTimer = 0;
scoreDisplay.textContent = score;
livesDisplay.textContent = lives;
gameOverScreen.style.display = 'none';
isGameOver = false;
gameRunning = true;
}
// --- Drawing Functions ---
function drawPlayer() {
ctx.fillStyle = player.color;
if (player.flashing && Math.floor(player.flashTimer / 100) % 2 === 0) {
ctx.fillStyle = '#ff0000'; // Flash red
} else {
ctx.fillStyle = player.color;
}
ctx.fillRect(player.x, player.y, player.width, player.height);
}
function drawProjectile(p) {
ctx.fillStyle = '#ffffff'; // White projectile
ctx.fillRect(p.x, p.y, p.width, p.height);
}
function drawTarget(target) {
ctx.fillStyle = target.color;
ctx.beginPath();
const halfWidth = target.width / 2;
const halfHeight = target.height / 2;
if (target.type === 0) { // Square
ctx.fillRect(target.x - halfWidth, target.y - halfHeight, target.width, target.height);
} else if (target.type === 1) { // Triangle
ctx.moveTo(target.x, target.y - halfHeight);
ctx.lineTo(target.x + halfWidth, target.y + halfHeight);
ctx.lineTo(target.x - halfWidth, target.y + halfHeight);
ctx.closePath();
ctx.fill();
} else if (target.type === 2) { // Circle
ctx.arc(target.x, target.y, halfWidth, 0, Math.PI * 2);
ctx.fill();
}
}
function drawExplosion(explosion) {
const elapsedTime = Date.now() - explosion.startTime;
const progress = elapsedTime / EXPLOSION_DURATION;
if (progress < 1) {
ctx.globalAlpha = 1 - progress; // Fade out
ctx.beginPath();
ctx.arc(explosion.x, explosion.y, explosion.radius * progress * 2, 0, Math.PI * 2); // Expanding circle
ctx.fillStyle = explosion.color;
ctx.fill();
ctx.globalAlpha = 1; // Reset alpha
}
}
// --- Game Logic ---
function update(deltaTime) {
if (isGameOver || !gameRunning) return;
// Update player movement
// Allow mouse control to override keyboard for x position
if (keysPressed['ArrowLeft']) {
player.x -= player.speed;
}
if (keysPressed['ArrowRight']) {
player.x += player.speed;
}
// If mouse is controlling, update player X
if (mouseX !== null) {
player.x = mouseX - player.width / 2;
}
// Keep player within bounds
if (player.x < 0) player.x = 0;
if (player.x + player.width > CANVAS_WIDTH) player.x = CANVAS_WIDTH - player.width;
// Player flashing effect
if (player.flashing) {
player.flashTimer += deltaTime;
if (player.flashTimer >= player.flashDuration) {
player.flashing = false;
}
}
// Handle shooting
const currentTime = Date.now();
if (keysPressed['Space'] || mouseIsDown) {
if (currentTime - lastShotTime > PROJECTILE_COOLDOWN) {
projectiles.push({
x: player.x + player.width / 2 - PROJECTILE_WIDTH / 2,
y: player.y,
width: PROJECTILE_WIDTH,
height: PROJECTILE_HEIGHT,
speed: PROJECTILE_SPEED
});
lastShotTime = currentTime;
}
}
// Update projectiles
for (let i = projectiles.length - 1; i >= 0; i--) {
const p = projectiles[i];
p.y -= p.speed;
// Remove if off-screen
if (p.y + p.height < 0) {
projectiles.splice(i, 1);
}
}
// Update targets
for (let i = targets.length - 1; i >= 0; i--) {
const target = targets[i];
target.y += target.speed;
// Target reaches bottom
if (target.y - target.height / 2 > CANVAS_HEIGHT) { // Check if target passed bottom
targets.splice(i, 1);
playerLoseLife();
continue; // Skip further checks for this target
}
// Projectile-target collision
for (let j = projectiles.length - 1; j >= 0; j--) {
const projectile = projectiles[j];
const targetRect = {
x: target.x - target.width / 2,
y: target.y - target.height / 2,
width: target.width,
height: target.height
};
if (checkCollision(projectile, targetRect)) {
explosions.push({
x: target.x,
y: target.y,
radius: target.width / 2,
color: target.color,
startTime: Date.now()
});
projectiles.splice(j, 1); // Remove projectile
targets.splice(i, 1); // Remove target
score += 10;
scoreDisplay.textContent = score;
break; // Target is hit, no need to check other projectiles against this target
}
}
}
// Spawn new targets
if (currentTime - lastTargetSpawnTime > TARGET_SPAWN_INTERVAL) {
createTarget();
lastTargetSpawnTime = currentTime;
}
// Gradually increase target speed over time
targetSpeed += TARGET_SPEED_INCREASE_RATE * deltaTime;
// Update explosions
for (let i = explosions.length - 1; i >= 0; i--) {
const explosion = explosions[i];
if (Date.now() - explosion.startTime > EXPLOSION_DURATION) {
explosions.splice(i, 1);
}
}
}
function draw() {
ctx.clearRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT); // Clear canvas
drawPlayer();
projectiles.forEach(drawProjectile);
targets.forEach(drawTarget);
explosions.forEach(drawExplosion);
}
function gameLoop(timestamp) {
if (!gameRunning) return;
const deltaTime = timestamp - lastTime;
lastTime = timestamp;
update(deltaTime);
draw();
animationFrameId = requestAnimationFrame(gameLoop);
}
// --- Event Listeners ---
document.addEventListener('keydown', (e) => {
keysPressed[e.key] = true;
if (e.key === ' ' || e.key === 'ArrowLeft' || e.key === 'ArrowRight') {
e.preventDefault(); // Prevent default browser scroll/behavior
}
});
document.addEventListener('keyup', (e) => {
keysPressed[e.key] = false;
});
canvas.addEventListener('mousemove', (e) => {
// Get mouse position relative to canvas
const rect = canvas.getBoundingClientRect();
const scaleX = canvas.width / rect.width;
mouseX = (e.clientX - rect.left) * scaleX;
});
canvas.addEventListener('mousedown', (e) => {
if (e.button === 0) { // Left click
mouseIsDown = true;
}
});
canvas.addEventListener('mouseup', (e) => {
if (e.button === 0) { // Left click
mouseIsDown = false;
}
});
restartButton.addEventListener('click', () => {
startGame();
});
// Initial game setup
function startGame() {
if (animationFrameId) {
cancelAnimationFrame(animationFrameId); // Ensure previous loop is stopped
}
resetGame();
lastTime = performance.now(); // Initialize lastTime for first frame
gameLoop(lastTime);
}
// Start the game on load
startGame();
});
給一個教程,告訴論壇用戶如何使用這個功能,要全面,包含製作表單等
不不不,教論壇用戶如何通過與你聊天創建互動遊戲,互動表單等。
抱歉,我誤解了您的意思!您是想知道如何透過與我對話來創建互動遊戲和表單,而不是手動編寫程式碼。這正是我的專長!
哈囉,論壇的朋友們!我是「Web Creator」,一個專為您設計的 AI 助手,我的任務就是將您的創意轉化為實際的互動式網頁組件,無論是遊戲、表單還是其他任何需要 HTML、CSS 和 JavaScript 結合的元素。
我住在這個 Discourse 私人訊息中,您可以直接在這裡向我描述您的想法。我會根據您的描述,逐步為您生成所需的程式碼(HTML、CSS、JavaScript)。
當您想創建一個互動組件時,請盡可能詳細地告訴我您的想法。這是我理解您需求,並為您生成最佳程式碼的關鍵。
請思考以下幾點:
好的請求範例:
「請創建一個復古風格的打磚塊遊戲。玩家控制底部的一個板子左右移動,用球擊碎螢幕上方的磚塊。需要有分數顯示、生命值、遊戲結束畫面。球碰到板子或磚塊時會有反彈效果,磚塊被擊碎時會有簡單的爆炸動畫。整個遊戲介面要有像素藝術的感覺。」
「我需要一個會員註冊表單。包含用戶名、電子郵件、密碼和確認密碼字段。所有字段都必須填寫。電子郵件需要格式驗證。密碼和確認密碼必須一致。表單提交後,顯示一個成功的訊息,如果失敗,則高亮顯示錯誤字段並提示錯誤原因。表單樣式要簡潔、現代。」
「請製作一個自動播放的圖片輪播器,有前後導航箭頭和底部的指示點。每張圖片停留 5 秒,可以淡入淡出切換效果。用戶點擊指示點或箭頭時可以手動切換。圖片內容是使用者提供的。」
不好的請求範例:
當您發出請求後,我會生成一個初步的 HTML、CSS 和 JavaScript 代碼結構。我會將其展示給您。
這時候,您就可以開始審閱了!
我會根據您的指令,修改現有的代碼,並再次展示給您。這個過程可以重複多次,直到您完全滿意為止。
範例對話流程:
您:「請生成一個簡單的猜數字遊戲。電腦生成一個 1-100 的數字,玩家輸入猜測,提示是『太高』或『太低』,直到猜對為止,顯示猜了多少次。」
我:(生成遊戲 HTML/CSS/JS) 「這是基礎的猜數字遊戲。您想試試看嗎?」
您:「很棒!現在請添加一個『重新開始』按鈕,並且在遊戲開始時,隱藏提示訊息,只顯示輸入框和提交按鈕。」
我:(更新 HTML/CSS/JS,添加按鈕和邏輯) 「好的,已添加重新開始按鈕,並調整了初始界面顯示。請查閱。」
… 依此類推。
一旦您對結果滿意,您可以直接將我提供的 HTML、CSS 和 JavaScript 代碼複製出來,保存到您的項目文件中(例如:index.html, style.css, script.js),然後在瀏覽器中運行。
與我合作創建網頁組件非常簡單:
期待與您一起創造更多有趣的互動式網頁體驗!現在,您可以開始向我提出您的第一個請求了!
請生成一個簡單的猜數字遊戲。電腦生成一個 1-100 的數字,玩家輸入猜測,提示是『太高』或『太低』,直到猜對為止,顯示猜了多少次。
好的,我理解了!您想要一個全新的互動遊戲——猜數字遊戲。
我會為您生成這個遊戲的 HTML、CSS 和 JavaScript 代碼。這個遊戲將會:
以下是為您設計的「猜數字遊戲」的代碼。
<div id="app">
<h1>Guess the Number!</h1>
<p>I'm thinking of a number between 1 and 100.</p>
<div id="feedback" aria-live="polite">Guess a number to start!</div>
<div id="attempts">Attempts: 0</div>
<div class="input-section">
<label for="guessInput">Enter your guess:</label>
<input type="number" id="guessInput" min="1" max="100" placeholder="e.g., 50">
<button id="guessButton">Guess</button>
</div>
<button id="restartButton" style="display: none;">Play Again</button>
</div>
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background-color: #f0f2f5;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
margin: 0;
color: #34495e;
}
#app {
background-color: #ffffff;
padding: 30px;
border-radius: 10px;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1);
text-align: center;
max-width: 400px;
width: 90%;
box-sizing: border-box;
}
h1 {
color: #2c3e50;
margin-bottom: 15px;
font-size: 2em;
}
p {
margin-bottom: 20px;
font-size: 1.1em;
line-height: 1.5;
}
#feedback {
min-height: 25px; /* To prevent layout shift */
font-weight: bold;
margin-bottom: 20px;
font-size: 1.2em;
color: #34495e; /* Default neutral color */
}
#feedback.error {
color: #e74c3c; /* Red for validation errors */
}
#feedback.correct {
color: #27ae60; /* Green for correct guess */
}
#attempts {
font-size: 1.1em;
margin-bottom: 25px;
color: #7f8c8d;
}
.input-section {
display: flex;
flex-direction: column;
gap: 15px;
margin-bottom: 25px;
}
label {
font-size: 1em;
margin-bottom: 5px;
text-align: left;
display: block;
}
input[type="number"] {
width: calc(100% - 20px); /* Adjust for padding */
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 1.1em;
outline: none;
transition: border-color 0.2s ease;
}
input[type="number"]:focus {
border-color: #3498db;
box-shadow: 0 0 5px rgba(52, 152, 219, 0.5);
}
button {
padding: 12px 20px;
border: none;
border-radius: 5px;
font-size: 1.1em;
cursor: pointer;
transition: background-color 0.2s ease, transform 0.1s ease;
width: 100%;
box-sizing: border-box;
}
#guessButton {
background-color: #3498db;
color: white;
}
#guessButton:hover:not(:disabled) {
background-color: #2980b9;
transform: translateY(-2px);
}
#guessButton:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
#restartButton {
background-color: #2ecc71;
color: white;
margin-top: 20px;
}
#restartButton:hover {
background-color: #27ae60;
transform: translateY(-2px);
}
/* Responsive adjustments */
@media (max-width: 600px) {
#app {
padding: 20px;
}
h1 {
font-size: 1.8em;
}
.input-section {
flex-direction: column;
align-items: stretch;
}
input[type="number"],
button {
font-size: 1em;
padding: 10px;
}
}
let targetNumber;
let attempts;
let gameOver;
const feedbackElement = document.getElementById('feedback');
const attemptsElement = document.getElementById('attempts');
const guessInput = document.getElementById('guessInput');
const guessButton = document.getElementById('guessButton');
const restartButton = document.getElementById('restartButton');
function initializeGame() {
targetNumber = Math.floor(Math.random() * 100) + 1; // Random number between 1 and 100
attempts = 0;
gameOver = false;
updateFeedback("Guess a number between 1 and 100!", false);
updateAttempts();
guessInput.value = '';
guessInput.focus(); // Focus on the input field for immediate entry
// Enable game controls
guessInput.disabled = false;
guessButton.disabled = false;
// Hide restart button
restartButton.style.display = 'none';
}
function updateFeedback(message, isError = false, isCorrect = false) {
feedbackElement.textContent = message;
feedbackElement.classList.remove('error', 'correct'); // Clear previous classes
if (isError) {
feedbackElement.classList.add('error');
} else if (isCorrect) {
feedbackElement.classList.add('correct');
}
}
function updateAttempts() {
attemptsElement.textContent = `Attempts: ${attempts}`;
}
function handleGuess() {
if (gameOver) {
// Game is over, do nothing
return;
}
const guess = parseInt(guessInput.value);
// Input validation
if (isNaN(guess) || guess < 1 || guess > 100) {
updateFeedback("Please enter a valid number between 1 and 100.", true);
guessInput.value = ''; // Clear invalid input
return;
}
attempts++;
updateAttempts();
if (guess < targetNumber) {
updateFeedback("Too low! Try again.");
} else if (guess > targetNumber) {
updateFeedback("Too high! Try again.");
} else {
updateFeedback(`Correct! You guessed the number in ${attempts} attempts!`, false, true);
gameOver = true;
// Disable game controls
guessInput.disabled = true;
guessButton.disabled = true;
// Show restart button
restartButton.style.display = 'block';
}
guessInput.value = ''; // Clear input field after each guess (even valid ones)
}
// Event Listeners
guessButton.addEventListener('click', handleGuess);
// Allow pressing Enter key to submit guess
guessInput.addEventListener('keydown', function(event) {
if (event.key === 'Enter') {
event.preventDefault(); // Prevent default form submission behavior if input is part of a form
handleGuess();
}
});
restartButton.addEventListener('click', initializeGame);
// Initialize the game when the DOM is fully loaded
document.addEventListener('DOMContentLoaded', initializeGame);