gpt4 book ai didi

javascript - 为什么我未完成的 javascript 游戏在第三次死亡后崩溃?

转载 作者:行者123 更新时间:2023-12-01 09:40:59 26 4
gpt4 key购买 nike

// Commented because does not work in Sandbox
// window.localStorage; //Ignore this line

// Where all my variables have been assigned

var c = document.getElementById("GameScreen");
var ctx = c.getContext("2d");
var charY = 220;
const gravity = 10;
var score = 0;
var time = 0;
var speed = 5;
var cloneID = 0;
var clonePos = [600];
var clonePoints = [0];
var animationBounce = 0;
var jump = 10;
var charDead = 0;
var dataCharY = [];
var dataDisObst = [];
var disObst = 1000;
var lowestLoopDis;
var jumpFactor = 0;
var disDeath;
var AIgames = 1;
var bestScoreAI = 0;

ctx.translate(c.width / 2, c.height / 2);

// Was going to use this for background trees but haven't done it yet

new obj(50, 50, 30, 30);

// Runs most functions

function runAll() {
if (charDead == 0) {
clearAll(); //This function runs most of the code
updateChar();
createGround();
updateObj();
groundDetect();
updateScore();
hitDetect();
addData();
testBetterAI();
getDisObst();
jumpAI();
removeUnusedObst();
}
}

// Was going to use this for trees but haven't yet

function obj(x, y, width, height) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;

ctx.beginPath();

ctx = c.getContext("2d");
ctx.fillStyle = "brown";
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = "green";
ctx.arc(-293, 150, 50, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();

this.cloneID = cloneID;
}

new obj(-293, 212, 0, 2 * Math.PI);

// Creates the floor (IKR)

function createGround() {
ctx.fillStyle = "green";
ctx.fillRect(-635, 250, c.width, 50);
}

// Creates the character every milisecond (or 10, I can't remember)

function updateChar() {
ctx.fillStyle = "blue";
ctx.fillRect(-300, charY - animationBounce, 15, 30);
ctx.fillStyle = "pink";
ctx.beginPath();
ctx.arc(-293, charY - animationBounce - 15, 15, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
}

// Removes everything in order to be redrawn in new position

function clearAll() {
ctx.clearRect(-700, -700, 2000, 2000);
}

// Redraws every square / object

function updateObj() {
for (var i = 0; i != clonePos.length; i++) {
ctx.fillStyle = "green";
ctx.fillRect(clonePos[i], 220, 30, 30);
}
}

// Creates new square (I also decided to rename them half way through with obstacle instead of object)

function createObst() {
clonePos.push(600);
cloneID++;
}

// Changes the squares / obstacles position relative to the movement

function moveObst() {
for (var ii = 0; ii != clonePos.length; ii++) {
clonePos[ii] -= speed;
}
}

// Tests to see if the character is on the ground

function groundDetect() {
if (charY > 220) {
charY = 220;
}
}

// Makes gravity actually work

function charGravity() {
if (charY < 220) {
charY += gravity;
}
}

// Updates the score counter text

function updateScore() {
document.getElementById("scoreText").innerHTML = score;
}

// Gives the character a little bounce when moving

function charBounce() {
setTimeout(function() {
animationBounce++;
}, 100);
setTimeout(function() {
animationBounce++;
}, 200);
setTimeout(function() {
animationBounce++;
}, 300);
setTimeout(function() {
animationBounce--;
}, 400);
setTimeout(function() {
animationBounce--;
}, 500);
setTimeout(function() {
animationBounce--;
}, 600);
}

// Makes the character jump

function charJump() {
if (charY == 220) {
jump = 4;

setTimeout(function() {
charY -= jump;
}, 20);
jump = 8;
setTimeout(function() {
charY -= jump;
}, 40);
jump = 12;
setTimeout(function() {
charY -= jump;
}, 60);
jump = 16;
setTimeout(function() {
charY -= jump;
}, 80);
setTimeout(function() {
charY -= jump;
}, 100);
setTimeout(function() {
charY -= jump;
}, 120);
}
}

// Detects when the character has a hit a square

function hitDetect() {
for (var iB = 0; iB != clonePos.length; iB++) {
if (clonePos[iB] > -320 && clonePos[iB] < -280 && charY > 200) {
charDied();
}
}
}

// Runs when character dies

function charDied() {
disDeath = disObst;
charDead = 1;

charRevive();

testBetterAI();

decideAdjustments();
}

// Adds score very interval

function addingScore() {
if (charDead == 0) {
score += 100;
}
}

// Adds to an array that I will use later

function addData() {
dataCharY.push(charY);
dataDisObst.push(disObst);
}

// Test to see if one of my AI's (which hasn't been made yet) scores is better than the previous best

function testBetterAI() {
// Commented because does not work in Sandbox
// if (score > localStorage.getItem("bestScore")) {
// }
}

// Calculates the distance to the nearest square / obstacle

function getDisObst() {
lowestLoopDis = 1000;

for (var iiA = 0; iiA != clonePos.length; iiA++) {
if (clonePos[iiA] > -320) {
if (clonePos[iiA] > 0) {
if (Math.abs(clonePos[iiA]) < lowestLoopDis) {
lowestLoopDis = Math.abs(clonePos[iiA]);
}
} else {
if (Math.abs(clonePos[iiA]) < lowestLoopDis) {
lowestLoopDis = Math.abs(clonePos[iiA]);
}
}
}
}

if (lowestLoopDis < disObst) {
disObst = lowestLoopDis;
}
}

// Increments the speed of the obstacles / squares and the character

function addSpeed() {
if (speed < 25) {
speed++;
}
}

// Restarts the game

function charRevive() {
clonePos = [600];
charDead = 0;
score = 0;
time = 0;
speed = 5;
AIgames++;
}

// I accidently did this twice, whoops

function testBetterAI() {
if (score > bestScoreAI) {
bestScoreAI = score;
}
}

// Makes the unfinished AI jump when it wants to

function jumpAI() {
if (disObst <= disDeath + jumpFactor) {
charJump();
}
}

// What changes need to be made in order to improve the AI

function decideAdjustments() {
jumpFactor += Math.floor(Math.random() * 10) - 5;

if (jumpFactor < 0) {
jumpFactor = 0;
}
}

// Removing blocks that are off the screen

function removeUnusedObst() {
if (clonePos[0] < -650) {
clonePos.shift();
}
}

// Intervals here

setInterval(function() {
time++;
}, 1000);
setInterval(function() {
runAll();
}, 10);
setInterval(function() {
moveObst();
}, 50);
setInterval(function() {
charGravity();
}, 25);
setInterval(function() {
createObst();
}, 3000);
setInterval(function() {
charBounce();
}, 650);
setInterval(function() {
addingScore();
}, 3500);
setInterval(function() {
addSpeed();
}, 25000);
#GameScreen {
background-color: CornflowerBlue;
}

#scoreText {
text-align: center;
font-size: 35px;
}
<div id="scoreText"></div>
<canvas id="GameScreen" width="1270px" height="550px"></canvas>

最佳答案

会发生什么

在您的hitDetect 函数中:

function hitDetect() {
for (var iB = 0; iB != clonePos.length; iB++) {
if (clonePos[iB] > -320 && clonePos[iB] < -280 && charY > 200) {
charDied();
}
}
}

您遍历 clonePos 数组,直到 iB 等于该数组的长度。如果满足条件(碰撞),则执行 charDied,而后者又执行 charRevive:

function charRevive() {
clonePos = [600];
// ...
}

与此同时,hitDetect 循环继续。并且在某一时刻(似乎是在你开始提高速度的时候),碰巧 iB 现在高于 1,这是新的长度clonePos。现在,会发生什么?好吧,你陷入了无限循环:

enter image description here

要吸取的教训

如果您正在循环一个可以在循环期间发生变异(并改变其长度)的数组,永远不要使用这种类型的条件:

i != myArr.length

如果您希望循环在某个时刻结束,请始终选择更严格的条件:

i < myArr.length

而且,更好的是,如果在满足条件后循环没有意义,则通过返回来结束此循环。例如:

function hitDetect() {
for (var iB = 0; iB < clonePos.length; iB++) {
if (clonePos[iB] > -320 && clonePos[iB] < -280 && charY > 200) {
return charDied();
// Alternatively, if there is other stuff to do after the loop, you can use:
// break;
}
}
}

固定代码

// Commented because does not work in Sandbox
// window.localStorage; //Ignore this line

// Where all my variables have been assigned

var c = document.getElementById("GameScreen");
var ctx = c.getContext("2d");
var charY = 220;
const gravity = 10;
var score = 0;
var time = 0;
var speed = 5;
var cloneID = 0;
var clonePos = [600];
var clonePoints = [0];
var animationBounce = 0;
var jump = 10;
var charDead = 0;
var dataCharY = [];
var dataDisObst = [];
var disObst = 1000;
var lowestLoopDis;
var jumpFactor = 0;
var disDeath;
var AIgames = 1;
var bestScoreAI = 0;

ctx.translate(c.width / 2, c.height / 2);

// Was going to use this for background trees but haven't done it yet

new obj(50, 50, 30, 30);

// Runs most functions

function runAll() {
if (charDead == 0) {
clearAll(); //This function runs most of the code
updateChar();
createGround();
updateObj();
groundDetect();
updateScore();
hitDetect();
addData();
testBetterAI();
getDisObst();
jumpAI();
removeUnusedObst();
}
}

// Was going to use this for trees but haven't yet

function obj(x, y, width, height) {
this.width = width;
this.height = height;
this.x = x;
this.y = y;

ctx.beginPath();

ctx = c.getContext("2d");
ctx.fillStyle = "brown";
ctx.fillRect(this.x, this.y, this.width, this.height);
ctx.fillStyle = "green";
ctx.arc(-293, 150, 50, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();

this.cloneID = cloneID;
}

new obj(-293, 212, 0, 2 * Math.PI);

// Creates the floor (IKR)

function createGround() {
ctx.fillStyle = "green";
ctx.fillRect(-635, 250, c.width, 50);
}

// Creates the character every milisecond (or 10, I can't remember)

function updateChar() {
ctx.fillStyle = "blue";
ctx.fillRect(-300, charY - animationBounce, 15, 30);
ctx.fillStyle = "pink";
ctx.beginPath();
ctx.arc(-293, charY - animationBounce - 15, 15, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
}

// Removes everything in order to be redrawn in new position

function clearAll() {
ctx.clearRect(-700, -700, 2000, 2000);
}

// Redraws every square / object

function updateObj() {
for (var i = 0; i < clonePos.length; i++) {
ctx.fillStyle = "green";
ctx.fillRect(clonePos[i], 220, 30, 30);
}
}

// Creates new square (I also decided to rename them half way through with obstacle instead of object)

function createObst() {
clonePos.push(600);
cloneID++;
}

// Changes the squares / obstacles position relative to the movement

function moveObst() {
for (var ii = 0; ii < clonePos.length; ii++) {
clonePos[ii] -= speed;
}
}

// Tests to see if the character is on the ground

function groundDetect() {
if (charY > 220) {
charY = 220;
}
}

// Makes gravity actually work

function charGravity() {
if (charY < 220) {
charY += gravity;
}
}

// Updates the score counter text

function updateScore() {
document.getElementById("scoreText").innerHTML = score;
}

// Gives the character a little bounce when moving

function charBounce() {
setTimeout(function() {
animationBounce++;
}, 100);
setTimeout(function() {
animationBounce++;
}, 200);
setTimeout(function() {
animationBounce++;
}, 300);
setTimeout(function() {
animationBounce--;
}, 400);
setTimeout(function() {
animationBounce--;
}, 500);
setTimeout(function() {
animationBounce--;
}, 600);
}

// Makes the character jump

function charJump() {
if (charY == 220) {
jump = 4;

setTimeout(function() {
charY -= jump;
}, 20);
jump = 8;
setTimeout(function() {
charY -= jump;
}, 40);
jump = 12;
setTimeout(function() {
charY -= jump;
}, 60);
jump = 16;
setTimeout(function() {
charY -= jump;
}, 80);
setTimeout(function() {
charY -= jump;
}, 100);
setTimeout(function() {
charY -= jump;
}, 120);
}
}

// Detects when the character has a hit a square

function hitDetect() {
for (var iB = 0; iB < clonePos.length; iB++) {
if (clonePos[iB] > -320 && clonePos[iB] < -280 && charY > 200) {
return charDied();
}
}
}

// Runs when character dies

function charDied() {
disDeath = disObst;
charDead = 1;

charRevive();

testBetterAI();

decideAdjustments();
}

// Adds score very interval

function addingScore() {
if (charDead == 0) {
score += 100;
}
}

// Adds to an array that I will use later

function addData() {
dataCharY.push(charY);
dataDisObst.push(disObst);
}

// Test to see if one of my AI's (which hasn't been made yet) scores is better than the previous best

function testBetterAI() {
// Commented because does not work in Sandbox
// if (score > localStorage.getItem("bestScore")) {
// }
}

// Calculates the distance to the nearest square / obstacle

function getDisObst() {
lowestLoopDis = 1000;

for (var iiA = 0; iiA < clonePos.length; iiA++) {
if (clonePos[iiA] > -320) {
if (clonePos[iiA] > 0) {
if (Math.abs(clonePos[iiA]) < lowestLoopDis) {
lowestLoopDis = Math.abs(clonePos[iiA]);
}
} else {
if (Math.abs(clonePos[iiA]) < lowestLoopDis) {
lowestLoopDis = Math.abs(clonePos[iiA]);
}
}
}
}

if (lowestLoopDis < disObst) {
disObst = lowestLoopDis;
}
}

// Increments the speed of the obstacles / squares and the character

function addSpeed() {
if (speed < 25) {
speed++;
}
}

// Restarts the game

function charRevive() {
clonePos = [600];
charDead = 0;
score = 0;
time = 0;
speed = 5;
AIgames++;
}

// I accidently did this twice, whoops

function testBetterAI() {
if (score > bestScoreAI) {
bestScoreAI = score;
}
}

// Makes the unfinished AI jump when it wants to

function jumpAI() {
if (disObst <= disDeath + jumpFactor) {
charJump();
}
}

// What changes need to be made in order to improve the AI

function decideAdjustments() {
jumpFactor += Math.floor(Math.random() * 10) - 5;

if (jumpFactor < 0) {
jumpFactor = 0;
}
}

// Removing blocks that are off the screen

function removeUnusedObst() {
if (clonePos[0] < -650) {
clonePos.shift();
}
}

// Intervals here

setInterval(function() {
time++;
}, 1000);
setInterval(function() {
runAll();
}, 10);
setInterval(function() {
moveObst();
}, 50);
setInterval(function() {
charGravity();
}, 25);
setInterval(function() {
createObst();
}, 3000);
setInterval(function() {
charBounce();
}, 650);
setInterval(function() {
addingScore();
}, 3500);
setInterval(function() {
addSpeed();
}, 25000);
body { text-align: center; }
#GameScreen {
background-color: CornflowerBlue;
width: 350px; height: 150px;
}
<div id="scoreText"></div>
<canvas id="GameScreen" width="1270px" height="550px"></canvas>

关于javascript - 为什么我未完成的 javascript 游戏在第三次死亡后崩溃?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60308666/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com