我正在创建一款恐龙游戏,其中通过单击(任意位置)或按空格键来触发跳跃。 我添加了最后一个阶段 (4),其中相同的按键仍会触发相同的功能
jump()
,但随后 jump()
将在第 4 阶段执行不同的操作(会有类似击中 Boss 之类的内容)。
当我使用点击时,我的代码按预期工作,但是当我使用空格时,在最后的第 4 阶段,
jump()
未按预期执行:它确实更新isJumping
我看到我放置的动画,但它没有不更新其他状态变量:craMessage
和craLife
。
为什么在这种情况下
Onclick
和 Onkeypress
的功能不一样?我的代码做错了什么?
提前谢谢您。
// src/App.js
import React, { useState, useEffect } from "react";
import Dino from "./components/Dino";
import Obstacle from "./components/Obstacle";
import Ground from "./components/Ground";
const App = () => {
const [isJumping, setIsJumping] = useState(false);
const [obstaclePosition, setObstaclePosition] = useState(1000);
const [score, setScore] = useState(0);
const [scoreMessage, setScoreMessage] = useState("");
const [phase, setPhase] = useState(1);
const [lastPhase, setLastPhase] = useState(1);
const [craLife, setCraLife] = useState(1000);
const [craMessage, setCraMessage] = useState("");
const [gameOver, setGameOver] = useState(false);
// Handle jump (both keyboard and mouse)
const jump = () => {
if (!isJumping) {
setIsJumping(true);
setTimeout(() => setIsJumping(false), 500); // Dino stays in the air for 300ms
if (phase === 4) {
//used same variable isJumping for hitting logic
let hit = Math.floor(Math.random() * 150 + 200); //Boss in phase 4 will be hit between 200 and 350
setCraMessage(`-${hit}`);
setCraLife(craLife - hit);
setTimeout(() => setCraMessage(""), 1000);
}
}
};
// Function to handle phase changes and difficulty scaling
const adjustPhase = (score) => {
if (score >= 10) {
if (lastPhase !== 4) {
// Show message only if phase changes
setPhase(4); // Phase 4: New game components
setScoreMessage("Phase 4: New Challenges!"); // Show message for Phase 4
setTimeout(() => setScoreMessage(""), 1000); // Remove message after 1 second
setLastPhase(4); // Update lastPhase
}
} else if (score >= 4) {
if (lastPhase !== 3) {
// Show message only if phase changes
setPhase(3); // Phase 3: Increase speed & randomize obstacle interval
setScoreMessage("Phase 3: Speeding Up & More Obstacles!"); // Show message for Phase 3
setTimeout(() => setScoreMessage(""), 1000); // Remove message after 1 second
setLastPhase(3); // Update lastPhase
}
} else if (score >= 2) {
if (lastPhase !== 2) {
// Show message only if phase changes
setPhase(2); // Phase 2: Increase speed
setScoreMessage("Phase 2: Speed Boost!"); // Show message for Phase 2
setTimeout(() => setScoreMessage(""), 1000); // Remove message after 1 second
setLastPhase(2); // Update lastPhase
}
} else {
if (lastPhase !== 1) {
// Show message only if phase changes
setPhase(1); // Phase 1: Initial state
setScoreMessage("Phase 1: Get Ready!"); // Show message for Phase 1
setTimeout(() => setScoreMessage(""), 1000); // Remove message after 1 second
setLastPhase(1); // Update lastPhase
}
}
};
// Move obstacle with changing intervals based on phase
useEffect(() => {
if (gameOver || phase === 4) return;
const baseInterval = 50; // Base interval (500ms for phase 1)
const speedIncreasePerPhase = 10; // Increase speed per phase (reduce interval by 100ms)
let interval = baseInterval - (phase - 1) * speedIncreasePerPhase; // Decrease interval as phase increases
const updateObstaclePosition = () => {
setObstaclePosition((prev) => {
if (prev <= -50) {
setScore((prevScore) => prevScore + 1);
if (phase === 3) {
return Math.random() * 500 + 500; // Randomize position between 800 and 1500
}
// In other phases, keep the position fixed
return 1000;
}
return prev - 10;
});
};
const intervalId = setInterval(updateObstaclePosition, interval);
return () => clearInterval(intervalId);
}, [gameOver, phase]);
useEffect(() => {
if (gameOver || phase !== 4 || craLife <= 0) return;
setScore((prevScore) => prevScore + 10);
}, [gameOver, phase, craLife]);
useEffect(() => {
adjustPhase(score); // Update phase based on score
}, [score]);
useEffect(() => {
// Ensure craLife doesn't go below 0
if (craLife <= 0) {
setCraLife(0); // Stop craLife from going negative
setScoreMessage("You win!");
setTimeout(() => setGameOver(true), 1000);
return;
}
if (obstaclePosition < 60 && obstaclePosition > 10 && !isJumping) {
if (phase === 4) {
if (craLife <= 0) {
setScoreMessage("You win!"); // If craLife is 0 or less, show win message
setGameOver(true); // End the game
return;
}
}
setGameOver(true); // Game ends in other phases regardless of craLife
}
}, [obstaclePosition, isJumping, phase, craLife]);
useEffect(() => {
const handleKeyDown = (e) => {
console.log("Keydown triggered:", e.key);
if (e.key === " ") {
jump();
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, []);
return (
<div
style={{
position: "relative",
height: "300px",
width: "100%",
overflow: "hidden",
background: "#ddd",
}}
onClick={jump} // Allow mouse clicks to trigger jumping
>
{gameOver ? (
<h1 style={{ textAlign: "center" }}>Game Over! Score: {score}</h1>
) : (
<>
<Dino phase={phase} isJumping={isJumping} />
<Obstacle
phase={phase}
position={obstaclePosition}
isLifted={isJumping}
/>
<Ground />
<div style={{ position: "absolute", top: "10px", left: "10px" }}>
Score: {score}
</div>
<div> Message: {scoreMessage} </div>
{phase === 4 && (
<>
<div> Cra Life: {craLife} </div>
<div
style={{
position: "absolute",
top: "50px",
right: "80px",
color: "red",
}}
>
{craMessage}
</div>
</>
)}
</>
)}
</div>
);
};
export default App;
在 keydown 中添加依赖项
useEffect(() => {
const handleKeyDown = (e) => {
if (e.key === " ") {
jump();
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [jump, isJumping, phase, craLife]); // Add dependencies