处理:蛇游戏运动逻辑
Processing: Snake Game Movement Logic
每吃一个苹果,蛇的移动速度就会翻倍。我似乎无法弄清楚是什么原因造成的。另外,让我感到困惑的另一件事是,每当我调用 background() 然后在其正下方调用 drawgrid 时,网格会在游戏开始时快速出现和消失,然后再也不会被绘制。任何帮助将不胜感激。这是代码:
class Sprite {
float x;
float y;
float [] dx = {0, 0, 20, -20};//up, down, right, left
float [] dy = {20, -20, 0, 0};//up, down, right, left
void update() {
x += dx[dir];
y += dy[dir];
}
}
class Body extends Sprite {
void render() {
pushMatrix();
stroke(255);
fill(0);
rect(x, y, bSize, bSize);
popMatrix();
}
void update() {
super.update();
if (Direction.equals("up")) {
dir = 1;
} else if (Direction.equals("down")) {
dir = 0;
} else if (Direction.equals("right")) {
dir = 2;
} else if (Direction.equals("left")) {
dir = 3;
}
if (dist(x, y, applex*bSize, appley*bSize) < 10) {
add = true;
applex = ceil(random(0, 38));
appley = ceil(random(0, 38));
}
}
}
int w = 50;
int h = 50;
float bSize;
color fillColor;
String Direction;
int dir = 2; //starting at the "right" direction
ArrayList<Body> sBody;
float applex;
float appley;
float prevX;
float prevY;
boolean add = false;
void setup() {
size(801, 801);
smooth();
//frameRate(12);
applex = ceil(random(0, 38));
appley = ceil(random(0, 38));
bSize = 20;
prevX = -5;
prevY = -5;
fillColor = color(0);
Direction = "right";
sBody = new ArrayList<Body>();
Body b = new Body();
sBody.add(b);
}
void draw() {
if (add) {
Body b = new Body();
sBody.add(b);
add = false;
}
if ((frameCount%5)==0) {
//background(255);
drawGrid();
fill(255, 0, 0);
rect(applex*bSize, appley*bSize, 20, 20);
for (Body t : sBody) {
if (prevX > -1 && prevY > -1) {
t.x = prevX;
t.y = prevY;
}
t.render();
t.update();
prevX = t.x;
prevY = t.y;
}
}
}
void keyPressed() {
if (key == CODED) {
if (Direction.equals("right") || Direction.equals("left")) {
if (keyCode == UP) {
Direction = "up";
}
if (keyCode == DOWN) {
Direction = "down";
}
}
if (Direction.equals("up") || Direction.equals("down")) {
if (keyCode == RIGHT) {
Direction = "right";
}
if (keyCode == LEFT) {
Direction = "left";
}
}
}
}
void drawGrid() {
for (int i = 0; i < height; i += 20) {
for (int j = 0; j < width; j += 20) {
pushMatrix();
fill(200);
stroke(255);
rect(i, j, bSize, bSize);
popMatrix();
}
}
}
////end of code////
你的逻辑有一些问题。
看看这个循环:
for (Body t : sBody) {
if (prevX > -1 && prevY > -1) {
t.x = prevX;
t.y = prevY;
}
t.render();
t.update();
prevX = t.x;
prevY = t.y;
}
请注意您如何在列表中的 每个 Body
对象上调用 update()
。这会导致蛇在每一段都移动,这就是为什么它变长时速度变快的原因。要修复that问题,只需要在蛇的head调用update()
,然后循环遍历其余部分段让它们跟随头部。
但这不是您唯一的问题。另请注意,在此循环退出后,prevX
和 prevY
将保留 last Body
对象在 sBody
列表中的值.然后在下次循环时,将蛇的 head 的位置设置为该位置。这没有任何意义,它会导致你的蛇从最后一段而不是头部 "steer"。
您的第三个问题是:您还设置了 prevX
和 prevY
的值 在 更新它们之后,这再次导致您的蛇行为不当。
因此,要解决所有这些问题,您需要做几件事:
- 只有
update()
蛇头
- 在每个循环之前设置
prevX
和prevY
,而不是将头部移动到结尾。
- 只循环遍历蛇的 rest 让它跟随头部。
- 使用临时变量,以便
prevX
和 prevY
设置为 t.x
和 t.y
在 之前 持有的值更新了它们。
最后,您的循环应如下所示:
//only move the head
sBody.get(0).update();
//set prevX and prevY to the head's position
prevX = sBody.get(0).x;
prevY = sBody.get(0).y;
for (Body t : sBody) {
//render ever piece, including the head
t.render();
//but don't move the head again
if (t == sBody.get(0)) {
continue;
}
//store the position before you change it
float tempX = t.x;
float tempY = t.y;
//change the position
t.x = prevX;
t.y = prevY;
//prevX and prevY hold the t.x and t.y values **before** you updated them
prevX = tempX;
prevY = tempY;
}
此外,值得注意的是,使用二维数组可能更容易实现。哦,你对 pushMatrix()
和 popMatrix()
的调用是不必要的,因为你实际上并没有修改矩阵。
如果您将 frameRate(5)
放入您的设置中,您就会明白为什么会发生这种情况,而且您将不需要 if ((frameCount%5)==0)
。基本上你有多少身体,整条蛇就跳过多少块!发生这种情况是因为您构建 for 循环的方式,它基本上以最后一个块是蛇头的方式呈现块。
如果我可以提出更好的解决方案。您真正需要更新的唯一块是我建议 sBody.get(0)
的蛇头。其余的块只需要有以前的位置,但你必须小心,每个单元格都得到前一个的位置!这是解决方案:
for (Body t : sBody) {
if (t == sBody.get(0)) {
// if its the first element (the head) store its
// position in prevX,prevY and update it afterwards
prevX = t.x;
prevY = t.y;
t.update();
} else {
// otherwise for other blocks, since we are
// using prevX, prevY for the previous block
// we need to store the current position
// of this block to give it back to prevX, prevY
float tpX = t.x;
float tpY = t.y;
t.x = prevX;
t.y = prevY;
prevX = tpX;
prevY = tpY;
}
t.render();
}
我在我的案例中没有看到网格问题,这可能是因为您正在使用那条 if ((frameCount%5)==0)
行...
每吃一个苹果,蛇的移动速度就会翻倍。我似乎无法弄清楚是什么原因造成的。另外,让我感到困惑的另一件事是,每当我调用 background() 然后在其正下方调用 drawgrid 时,网格会在游戏开始时快速出现和消失,然后再也不会被绘制。任何帮助将不胜感激。这是代码:
class Sprite {
float x;
float y;
float [] dx = {0, 0, 20, -20};//up, down, right, left
float [] dy = {20, -20, 0, 0};//up, down, right, left
void update() {
x += dx[dir];
y += dy[dir];
}
}
class Body extends Sprite {
void render() {
pushMatrix();
stroke(255);
fill(0);
rect(x, y, bSize, bSize);
popMatrix();
}
void update() {
super.update();
if (Direction.equals("up")) {
dir = 1;
} else if (Direction.equals("down")) {
dir = 0;
} else if (Direction.equals("right")) {
dir = 2;
} else if (Direction.equals("left")) {
dir = 3;
}
if (dist(x, y, applex*bSize, appley*bSize) < 10) {
add = true;
applex = ceil(random(0, 38));
appley = ceil(random(0, 38));
}
}
}
int w = 50;
int h = 50;
float bSize;
color fillColor;
String Direction;
int dir = 2; //starting at the "right" direction
ArrayList<Body> sBody;
float applex;
float appley;
float prevX;
float prevY;
boolean add = false;
void setup() {
size(801, 801);
smooth();
//frameRate(12);
applex = ceil(random(0, 38));
appley = ceil(random(0, 38));
bSize = 20;
prevX = -5;
prevY = -5;
fillColor = color(0);
Direction = "right";
sBody = new ArrayList<Body>();
Body b = new Body();
sBody.add(b);
}
void draw() {
if (add) {
Body b = new Body();
sBody.add(b);
add = false;
}
if ((frameCount%5)==0) {
//background(255);
drawGrid();
fill(255, 0, 0);
rect(applex*bSize, appley*bSize, 20, 20);
for (Body t : sBody) {
if (prevX > -1 && prevY > -1) {
t.x = prevX;
t.y = prevY;
}
t.render();
t.update();
prevX = t.x;
prevY = t.y;
}
}
}
void keyPressed() {
if (key == CODED) {
if (Direction.equals("right") || Direction.equals("left")) {
if (keyCode == UP) {
Direction = "up";
}
if (keyCode == DOWN) {
Direction = "down";
}
}
if (Direction.equals("up") || Direction.equals("down")) {
if (keyCode == RIGHT) {
Direction = "right";
}
if (keyCode == LEFT) {
Direction = "left";
}
}
}
}
void drawGrid() {
for (int i = 0; i < height; i += 20) {
for (int j = 0; j < width; j += 20) {
pushMatrix();
fill(200);
stroke(255);
rect(i, j, bSize, bSize);
popMatrix();
}
}
}
////end of code////
你的逻辑有一些问题。
看看这个循环:
for (Body t : sBody) {
if (prevX > -1 && prevY > -1) {
t.x = prevX;
t.y = prevY;
}
t.render();
t.update();
prevX = t.x;
prevY = t.y;
}
请注意您如何在列表中的 每个 Body
对象上调用 update()
。这会导致蛇在每一段都移动,这就是为什么它变长时速度变快的原因。要修复that问题,只需要在蛇的head调用update()
,然后循环遍历其余部分段让它们跟随头部。
但这不是您唯一的问题。另请注意,在此循环退出后,prevX
和 prevY
将保留 last Body
对象在 sBody
列表中的值.然后在下次循环时,将蛇的 head 的位置设置为该位置。这没有任何意义,它会导致你的蛇从最后一段而不是头部 "steer"。
您的第三个问题是:您还设置了 prevX
和 prevY
的值 在 更新它们之后,这再次导致您的蛇行为不当。
因此,要解决所有这些问题,您需要做几件事:
- 只有
update()
蛇头 - 在每个循环之前设置
prevX
和prevY
,而不是将头部移动到结尾。 - 只循环遍历蛇的 rest 让它跟随头部。
- 使用临时变量,以便
prevX
和prevY
设置为t.x
和t.y
在 之前 持有的值更新了它们。
最后,您的循环应如下所示:
//only move the head
sBody.get(0).update();
//set prevX and prevY to the head's position
prevX = sBody.get(0).x;
prevY = sBody.get(0).y;
for (Body t : sBody) {
//render ever piece, including the head
t.render();
//but don't move the head again
if (t == sBody.get(0)) {
continue;
}
//store the position before you change it
float tempX = t.x;
float tempY = t.y;
//change the position
t.x = prevX;
t.y = prevY;
//prevX and prevY hold the t.x and t.y values **before** you updated them
prevX = tempX;
prevY = tempY;
}
此外,值得注意的是,使用二维数组可能更容易实现。哦,你对 pushMatrix()
和 popMatrix()
的调用是不必要的,因为你实际上并没有修改矩阵。
如果您将 frameRate(5)
放入您的设置中,您就会明白为什么会发生这种情况,而且您将不需要 if ((frameCount%5)==0)
。基本上你有多少身体,整条蛇就跳过多少块!发生这种情况是因为您构建 for 循环的方式,它基本上以最后一个块是蛇头的方式呈现块。
如果我可以提出更好的解决方案。您真正需要更新的唯一块是我建议 sBody.get(0)
的蛇头。其余的块只需要有以前的位置,但你必须小心,每个单元格都得到前一个的位置!这是解决方案:
for (Body t : sBody) {
if (t == sBody.get(0)) {
// if its the first element (the head) store its
// position in prevX,prevY and update it afterwards
prevX = t.x;
prevY = t.y;
t.update();
} else {
// otherwise for other blocks, since we are
// using prevX, prevY for the previous block
// we need to store the current position
// of this block to give it back to prevX, prevY
float tpX = t.x;
float tpY = t.y;
t.x = prevX;
t.y = prevY;
prevX = tpX;
prevY = tpY;
}
t.render();
}
我在我的案例中没有看到网格问题,这可能是因为您正在使用那条 if ((frameCount%5)==0)
行...