为什么它立即让玩家输了
Why does it instantly have the player lose
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;
function setup() {
smooth();
frameRate(999)
createCanvas(600, 450);
playerX = 500;
playerY = 100;
}
function draw() {
var TotalBlue = 0;
var TotalRed = 0;
var Total = 0;
var cellDist = [];
if (lost) {
noLoop()
fill(255)
textSize(40)
background(0)
text("You lost", width / 2.5, height / 2)
textSize(20)
text("Final Board: ", 350, 60)
} else {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
Newcelltimer++;
if (Newcelltimer % 40 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 200 == 0) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
if (Newcelltimer == 1 || Newcelltimer == 2) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
//Checks if player Ate cell
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
playerX -= playerSpeed;
}
if (Newcelltimer % 200 == 0) {
cell.splice(0, 2)
}
for (var j = 0; j < (cpu.length / 4); j++) {
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
} else {
cellDist.push(dis)
}
}
var ClosestCell = min(cellDist);
var ClosestCellpos;
for (var r = 0; r < cell.length / 2; r++) {
if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
ClosestCellpos = r;
break;
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
if (r < 100 && dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 || cpu[j * 4 + 2] > playerSize) {
var disXpos = cell[r * 2] - cpu[j * 4];
var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];
disXpos = map(disXpos, -100, 100, -1, 1);
disYpos = map(disYpos, -100, 100, -1, 1);
cpu[j * 4] += disXpos * amp;
cpu[j * 4 + 1] += disYpos * amp;
} else {
x += 0.003;
y += 0.003;
let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
cpu[j * 4] += offsetX;
cpu[j * 4 + 1] += offsetY;
}
//Draws the AI's
if (cpu[j * 4 + 3] % 2 == 0) {
fill(0, 0, 255)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
} else {
fill(255, 0, 0)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
}
//Checks if player ate AI or vice versa
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
//Checks if one AI eats another
for (var m = 0; m < cpu.length / 4; m++) {
if (m != j) {
if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]
if (higher > distant) {
if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
cpu[m * 4 + 2] += cpu[j * 4 + 2]
cpu.splice(j * 4, 4)
} else {
cpu[j * 4 + 2] += cpu[m * 4 + 2]
cpu.splice(m * 4, 4)
} //Else
} // If
} //If
} //If
} //If
} //Nested For
} // For
//Draws all the "cells"
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
//Nothing important, drawing the smiley face character
fill(255, 255, 0)
circle(playerX, playerY, playerSize)
fill(0)
ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
fill(255, 255, 0)
noStroke()
arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
stroke(0)
//Limits the max player size
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
}
VS
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;
function setup() {
smooth();
frameRate(999)
createCanvas(600, 450);
playerX = 500;
playerY = 100;
}
function draw() {
var TotalBlue = 0;
var TotalRed = 0;
var Total = 0;
var cellDist = [];
if (lost) {
noLoop()
fill(255)
textSize(40)
background(0)
text("You lost", width / 2.5, height / 2)
textSize(20)
text("Final Board: ", 350, 60)
} else {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
Newcelltimer++;
if (Newcelltimer % 40 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 200 == 0) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
if (Newcelltimer == 1 || Newcelltimer == 2) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
//Checks if player Ate cell
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
playerX -= playerSpeed;
}
if (Newcelltimer % 200 == 0) {
cell.splice(0, 2)
}
for (var j = 0; j < (cpu.length / 4); j++) {
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
x += 0.003;
y += 0.003;
let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
cpu[j * 4] += offsetX;
cpu[j * 4 + 1] += offsetY;
//Draws the AI's
if (cpu[j * 4 + 3] % 2 == 0) {
fill(0, 0, 255)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
} else {
fill(255, 0, 0)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
}
//Checks if player ate AI or vice versa
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
//Checks if one AI eats another
for (var m = 0; m < cpu.length / 4; m++) {
if (m != j) {
if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]
if (higher > distant) {
if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
cpu[m * 4 + 2] += cpu[j * 4 + 2]
cpu.splice(j * 4, 4)
} else {
cpu[j * 4 + 2] += cpu[m * 4 + 2]
cpu.splice(m * 4, 4)
} //Else
} // If
} //If
} //If
} //If
} //Nested For
} // For
//Draws all the "cells"
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
//Nothing important, drawing the smiley face character
fill(255, 255, 0)
circle(playerX, playerY, playerSize)
fill(0)
ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
fill(255, 255, 0)
noStroke()
arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
stroke(0)
//Limits the max player size
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
}
首先我知道这甚至不接近最小可重现代码,但我试图用一些注释来清理它。我不确定要删除什么,所以我 100% 对对此 post 所做的任何编辑持开放态度。话虽如此,我的问题是为什么最重要的一个不起作用。我应该弄清楚我要做什么,在伪代码中看起来像这样:
- Return 包含单元格和 AI 之间所有距离的数组
- 找到该数组中的最小值
- 找出单元格的X和Y位置
- 检查该数组中的最小值是否小于任意 100,AND EITHER AI 的大小大于玩家的,OR 玩家和AI之间的距离小于另一个任意100
- 如果为假,继续使用 Perlin 噪声计算 AI 的下一步行动
- 如果为真,计算AI离cell的X距离和Y距离
- 使用这些距离,将其映射到 -1 和 1,然后将其乘以振幅,然后只需将 AI 移动您获得的值即可。
我要问的是,为什么这不是首先起作用的,以及如何使其起作用。
我怀疑AI在整个地图上都失去了控制,并且由于AI的初始大小比玩家大,所以玩家输了。
很可能我的程序不会加载到代码段工具中,所以这里是 Web 编辑器上程序的链接
第一个(不工作)- https://editor.p5js.org/Meowmeow/sketches/5725Ik6AF
第二个(工作)- https://editor.p5js.org/Meowmeow/sketches/XTH-hArn6
如果问题不清楚,请写下您不明白的地方,因为我不确定没有任何背景信息的其他人是否很难理解发生了什么。
编辑)刚刚意识到该列表不适用于伪代码,我现在没有时间修复它。 (固定)
-编辑)
只是为了清除它,我希望 CPUs 有一个更具战略性、随机性更少的路径,为此我首先执行上面所述的以下操作(让 CPU 吃掉一个单元格如果附近有的话)
玩家立即失败的原因是检查 AI“cpu”与玩家距离的代码无法正常工作。
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
} else {
cellDist.push(dis)
}
}
// NOTE: if there are no entries in cpu for which the condition in the above if block was false, then cellDist will be empty
var ClosestCell = min(cellDist);
// NOTE: if cellDist is empty, then ClosestCell will be Infinity
var ClosestCellpos;
for (var r = 0; r < cell.length / 2; r++) {
// NOTE: If ClosestCell is Infinity than this will never be true, and ClosestCellpos will be undefined
if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
ClosestCellpos = r;
break;
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
// NOTE: This is bad form: using r from the above for loop. If you are going to use a variable that is initialized/incremented by a for loop you should declare it separately outside of the for loop. Perhaps you should be using ClosestCellpos instead of r?
// NOTE: r < 100 is strange. what does that mean/matter? is cell.length / 2 guaranteed to be >= 100?
if (r < 100 &&
dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 ||
// NOTE: because this is after a logical OR this can succeed even if the value of r is >= cell.length / 2
cpu[j * 4 + 2] > playerSize) {
// NOTE: when r is >= cell.length / 2 + 1 one or both of these become NaN
var disXpos = cell[r * 2] - cpu[j * 4];
var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];
// When disXpos or disYpos are NaN we start putting NaN values into the cpu array
disXpos = map(disXpos, -100, 100, -1, 1);
disYpos = map(disYpos, -100, 100, -1, 1);
cpu[j * 4] += disXpos * amp;
cpu[j * 4 + 1] += disYpos * amp;
}
// .........
// NOTE: the int() function converts NaN into 0, which is unfortunate. You should use floor() instead of int()
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
// NOTE: Once distance is zero because if the above series of notes, this becomes true, which happens immediately
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
这是一个 working version。我搬到 OpenProcessing.org 是因为 p5js.org 编辑器不能很好地调试。我能够通过简单地在 list = true;
之前抛出一个 debugger;
语句然后向后工作来找到这个问题。您需要打开浏览器的开发人员工具面板才能使 debugger;
语句生效。
注意:这个草图有很多代码味道问题,很难调试。
- 永远不要使用
var
。始终使用 let
。
- 单元格和 cpu 数据结构令人困惑且难以理解。与其像这样将 x 和 y 值打包到数组中,不如将这些数据结构表示为对象数组要好得多。我仍然不理解这些数组中的所有
n * 2
和 j * 4
索引。必须有更好的方法来模拟您的状态。
但是您很好地为可运行的示例提供了 link,否则将无法确定您的问题。
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;
function setup() {
smooth();
frameRate(999)
createCanvas(600, 450);
playerX = 500;
playerY = 100;
}
function draw() {
var TotalBlue = 0;
var TotalRed = 0;
var Total = 0;
var cellDist = [];
if (lost) {
noLoop()
fill(255)
textSize(40)
background(0)
text("You lost", width / 2.5, height / 2)
textSize(20)
text("Final Board: ", 350, 60)
} else {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
Newcelltimer++;
if (Newcelltimer % 40 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 200 == 0) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
if (Newcelltimer == 1 || Newcelltimer == 2) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
//Checks if player Ate cell
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
playerX -= playerSpeed;
}
if (Newcelltimer % 200 == 0) {
cell.splice(0, 2)
}
for (var j = 0; j < (cpu.length / 4); j++) {
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
} else {
cellDist.push(dis)
}
}
var ClosestCell = min(cellDist);
var ClosestCellpos;
for (var r = 0; r < cell.length / 2; r++) {
if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
ClosestCellpos = r;
break;
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
if (r < 100 && dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 || cpu[j * 4 + 2] > playerSize) {
var disXpos = cell[r * 2] - cpu[j * 4];
var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];
disXpos = map(disXpos, -100, 100, -1, 1);
disYpos = map(disYpos, -100, 100, -1, 1);
cpu[j * 4] += disXpos * amp;
cpu[j * 4 + 1] += disYpos * amp;
} else {
x += 0.003;
y += 0.003;
let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
cpu[j * 4] += offsetX;
cpu[j * 4 + 1] += offsetY;
}
//Draws the AI's
if (cpu[j * 4 + 3] % 2 == 0) {
fill(0, 0, 255)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
} else {
fill(255, 0, 0)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
}
//Checks if player ate AI or vice versa
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
//Checks if one AI eats another
for (var m = 0; m < cpu.length / 4; m++) {
if (m != j) {
if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]
if (higher > distant) {
if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
cpu[m * 4 + 2] += cpu[j * 4 + 2]
cpu.splice(j * 4, 4)
} else {
cpu[j * 4 + 2] += cpu[m * 4 + 2]
cpu.splice(m * 4, 4)
} //Else
} // If
} //If
} //If
} //If
} //Nested For
} // For
//Draws all the "cells"
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
//Nothing important, drawing the smiley face character
fill(255, 255, 0)
circle(playerX, playerY, playerSize)
fill(0)
ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
fill(255, 255, 0)
noStroke()
arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
stroke(0)
//Limits the max player size
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
}
VS
var playerX;
var playerY;
var playerSize = 15;
var playerSpeed = (playerSize / Math.pow(playerSize, 1.44)) * 10;
var Newcelltimer = 0;
var cell = []
var cellEaten = 0;
var celliseaten = false;
var eaten = false;
var zoom = 1;
var n = 0;
var Xgrid = 600;
var Ygrid = 600;
var cpu = [];
var x = 0;
var y = 10;
var z = 100;
var OffSetX = [];
var OffSetY = [];
var lost = false;
var CPUteam = 2;
function setup() {
smooth();
frameRate(999)
createCanvas(600, 450);
playerX = 500;
playerY = 100;
}
function draw() {
var TotalBlue = 0;
var TotalRed = 0;
var Total = 0;
var cellDist = [];
if (lost) {
noLoop()
fill(255)
textSize(40)
background(0)
text("You lost", width / 2.5, height / 2)
textSize(20)
text("Final Board: ", 350, 60)
} else {
background(220);
push();
var Newzoom = 10 / playerSize
let newnewZoom = 1.3 * lerp(0.9, 10 / playerSize, 0.5)
Newzoom = lerp(zoom, Newzoom, 0.3)
translate(Xgrid / 2, Ygrid / 2 - 50);
scale(newnewZoom)
translate(-playerX, -playerY);
playerSpeed = round((playerSize / Math.pow(playerSize, 1.44)) * 10000) / 1000
Newcelltimer++;
if (Newcelltimer % 40 == 0) {
cell.push(ceil(random(0 - Xgrid, 2 * Xgrid)),
ceil(random(0 - Ygrid, 2 * Ygrid)))
}
if (Newcelltimer % 200 == 0) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
if (Newcelltimer == 1 || Newcelltimer == 2) {
cpu.push(ceil(random(-Xgrid, 2 * Xgrid)), ceil(random(-Ygrid, 2 * Ygrid)), 20, CPUteam)
OffSetX.push(ceil(random(0, 1000000)))
OffSetY.push(ceil(random(1000000, 2000000)))
CPUteam++;
}
//Checks if player Ate cell
for (var i = 0; i < cell.length / 2; i++) {
let d = int(dist(cell[i * 2], cell[i * 2 + 1], playerX, playerY))
if (d <= playerSize / 2) {
playerSize += 5;
cell.splice(i * 2, 2)
celliseaten = true;
}
}
if (keyIsDown(UP_ARROW) && playerY > 0 - Ygrid) {
playerY -= playerSpeed;
}
if (keyIsDown(RIGHT_ARROW) && playerX < 2 * Xgrid) {
playerX += playerSpeed;
}
if (keyIsDown(DOWN_ARROW) && playerY < 2 * Ygrid) {
playerY += playerSpeed;
}
if (keyIsDown(LEFT_ARROW) && playerX > 0 - Xgrid) {
playerX -= playerSpeed;
}
if (Newcelltimer % 200 == 0) {
cell.splice(0, 2)
}
for (var j = 0; j < (cpu.length / 4); j++) {
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
x += 0.003;
y += 0.003;
let offsetX = map(noise(x + OffSetX[j]), 0, 1, -1, 1) * amp;
let offsetY = map(noise(y + OffSetY[j]), 0, 1, -1, 1) * amp;
cpu[j * 4] += offsetX;
cpu[j * 4 + 1] += offsetY;
//Draws the AI's
if (cpu[j * 4 + 3] % 2 == 0) {
fill(0, 0, 255)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2]);
} else {
fill(255, 0, 0)
circle(cpu[j * 4], cpu[j * 4 + 1], cpu[j * 4 + 2])
}
//Checks if player ate AI or vice versa
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
//Checks if one AI eats another
for (var m = 0; m < cpu.length / 4; m++) {
if (m != j) {
if (cpu[j * 4 + 3] % 2 != cpu[m * 4 + 3] % 2) {
distant = dist(cpu[m * 4], cpu[m * 4 + 1], cpu[j * 4], cpu[j * 4 + 1])
let higher = (cpu[m * 4 + 2] > cpu[j * 4 + 2]) ? cpu[m * 4 + 2] : cpu[j * 4 + 2]
if (higher > distant) {
if (cpu[m * 4 + 2] > cpu[j * 4 + 2]) {
cpu[m * 4 + 2] += cpu[j * 4 + 2]
cpu.splice(j * 4, 4)
} else {
cpu[j * 4 + 2] += cpu[m * 4 + 2]
cpu.splice(m * 4, 4)
} //Else
} // If
} //If
} //If
} //If
} //Nested For
} // For
//Draws all the "cells"
for (var k = 0; k < cell.length / 2; k++) {
fill(0, 255, 255, 100)
circle(cell[k * 2], cell[k * 2 + 1], 7)
}
//Nothing important, drawing the smiley face character
fill(255, 255, 0)
circle(playerX, playerY, playerSize)
fill(0)
ellipse(playerX - playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
ellipse(playerX + playerSize / 5, playerY - playerSize / 10, playerSize / 5, playerSize / 3)
arc(playerX, playerY + playerSize / 5, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
fill(255, 255, 0)
noStroke()
arc(playerX, (playerY + playerSize / 5) - 1, playerSize / 2, playerSize / 5, 0, 3.2, PIE)
stroke(0)
//Limits the max player size
if (playerSize >= 3 * Xgrid | playerSize >= 3 * Ygrid) {
if (Xgrid > Ygrid) {
playerSize = 3 * Ygrid;
} else {
playerSize = 3 * Xgrid;
}
}
}
首先我知道这甚至不接近最小可重现代码,但我试图用一些注释来清理它。我不确定要删除什么,所以我 100% 对对此 post 所做的任何编辑持开放态度。话虽如此,我的问题是为什么最重要的一个不起作用。我应该弄清楚我要做什么,在伪代码中看起来像这样:
- Return 包含单元格和 AI 之间所有距离的数组
- 找到该数组中的最小值
- 找出单元格的X和Y位置
- 检查该数组中的最小值是否小于任意 100,AND EITHER AI 的大小大于玩家的,OR 玩家和AI之间的距离小于另一个任意100
- 如果为假,继续使用 Perlin 噪声计算 AI 的下一步行动
- 如果为真,计算AI离cell的X距离和Y距离
- 使用这些距离,将其映射到 -1 和 1,然后将其乘以振幅,然后只需将 AI 移动您获得的值即可。
我要问的是,为什么这不是首先起作用的,以及如何使其起作用。 我怀疑AI在整个地图上都失去了控制,并且由于AI的初始大小比玩家大,所以玩家输了。
很可能我的程序不会加载到代码段工具中,所以这里是 Web 编辑器上程序的链接
第一个(不工作)- https://editor.p5js.org/Meowmeow/sketches/5725Ik6AF
第二个(工作)- https://editor.p5js.org/Meowmeow/sketches/XTH-hArn6
如果问题不清楚,请写下您不明白的地方,因为我不确定没有任何背景信息的其他人是否很难理解发生了什么。
编辑)刚刚意识到该列表不适用于伪代码,我现在没有时间修复它。 (固定)
-编辑) 只是为了清除它,我希望 CPUs 有一个更具战略性、随机性更少的路径,为此我首先执行上面所述的以下操作(让 CPU 吃掉一个单元格如果附近有的话)
玩家立即失败的原因是检查 AI“cpu”与玩家距离的代码无法正常工作。
var cpuDist = [];
//Checks if AI ate cell
for (var n = 0; n < cell.length / 2; n++) {
let dis = int(dist(cell[n * 2], cell[n * 2 + 1], cpu[j * 4], cpu[j * 4 + 1]))
if (dis <= cpu[j * 4 + 2] / 2) {
cpu[j * 4 + 2] += 5;
cell.splice(n * 2, 2)
} else {
cellDist.push(dis)
}
}
// NOTE: if there are no entries in cpu for which the condition in the above if block was false, then cellDist will be empty
var ClosestCell = min(cellDist);
// NOTE: if cellDist is empty, then ClosestCell will be Infinity
var ClosestCellpos;
for (var r = 0; r < cell.length / 2; r++) {
// NOTE: If ClosestCell is Infinity than this will never be true, and ClosestCellpos will be undefined
if (ClosestCell == dist(cpu[j * 4], cpu[j * 4 + 1], cell[r * 2], cell[r * 2 + 1])) {
ClosestCellpos = r;
break;
}
}
let amp = round((cpu[j * 4 + 2] / Math.pow(cpu[j * 4 + 2], 1.44)) * 10000) / 1000;
// NOTE: This is bad form: using r from the above for loop. If you are going to use a variable that is initialized/incremented by a for loop you should declare it separately outside of the for loop. Perhaps you should be using ClosestCellpos instead of r?
// NOTE: r < 100 is strange. what does that mean/matter? is cell.length / 2 guaranteed to be >= 100?
if (r < 100 &&
dist(playerX, playerY, cpu[j * 4], cpu[j * 4 + 1]) > 100 ||
// NOTE: because this is after a logical OR this can succeed even if the value of r is >= cell.length / 2
cpu[j * 4 + 2] > playerSize) {
// NOTE: when r is >= cell.length / 2 + 1 one or both of these become NaN
var disXpos = cell[r * 2] - cpu[j * 4];
var disYpos = cell[r * 2 + 1] - cpu[j * 4 + 1];
// When disXpos or disYpos are NaN we start putting NaN values into the cpu array
disXpos = map(disXpos, -100, 100, -1, 1);
disYpos = map(disYpos, -100, 100, -1, 1);
cpu[j * 4] += disXpos * amp;
cpu[j * 4 + 1] += disYpos * amp;
}
// .........
// NOTE: the int() function converts NaN into 0, which is unfortunate. You should use floor() instead of int()
let distance = int(dist(cpu[j * 4], cpu[j * 4 + 1], playerX, playerY))
if (distance <= playerSize / 2 && cpu[j * 4 + 2] < playerSize) {
playerSize += floor(cpu[j * 4 + 2]);
cpu.splice(j * 4, 4)
}
// NOTE: Once distance is zero because if the above series of notes, this becomes true, which happens immediately
if (distance <= cpu[j * 4 + 2] && cpu[j * 4 + 2] > playerSize) {
lost = true;
}
这是一个 working version。我搬到 OpenProcessing.org 是因为 p5js.org 编辑器不能很好地调试。我能够通过简单地在 list = true;
之前抛出一个 debugger;
语句然后向后工作来找到这个问题。您需要打开浏览器的开发人员工具面板才能使 debugger;
语句生效。
注意:这个草图有很多代码味道问题,很难调试。
- 永远不要使用
var
。始终使用let
。 - 单元格和 cpu 数据结构令人困惑且难以理解。与其像这样将 x 和 y 值打包到数组中,不如将这些数据结构表示为对象数组要好得多。我仍然不理解这些数组中的所有
n * 2
和j * 4
索引。必须有更好的方法来模拟您的状态。
但是您很好地为可运行的示例提供了 link,否则将无法确定您的问题。