Processing登月游戏控件失效求助:新手代码问题排查
嘿,我帮你梳理了代码里的几个关键问题,咱们一步步修复,让你的登月游戏正常运行起来!
1. 重力没真正生效(你以为的重力其实是初始速度)
你的代码里定义了gravity变量,但从来没在每一帧更新vy!飞船下落只是因为初始vy=1,不是真的重力作用。要在draw()函数里添加:
vy += gravity; // 每一帧给y方向速度加上重力加速度
2. 移动控制逻辑错误
- 误用
translate():moveKeys()里的translate()是移动整个画布坐标系,不是飞船位置,这会导致后续绘制混乱。应该直接控制飞船的速度或位置。 - 未处理按键松开事件:只写了
keyPressed没写keyReleased,导致按住方向键后状态一直是true,松开也停不下来。 - 推力逻辑搞反:Processing的y轴向下,
vy越大下落越快,向上推力应该减小vy(甚至让它变负实现向上飞),而不是增加。
修复后的按键相关函数:
void keyPressed() { if (key == CODED) { switch (keyCode) { case UP: moveUp = true; break; case LEFT: moveLeft = true; break; case RIGHT: moveRight = true; break; } } } void keyReleased() { if (key == CODED) { switch (keyCode) { case UP: moveUp = false; break; case LEFT: moveLeft = false; break; case RIGHT: moveRight = false; break; } } } void moveKeys() { // 控制左右移动速度 if (moveLeft) { vx = -1; } else if (moveRight) { vx = 1; } else { vx = 0; // 松开按键后停止左右移动 } if (moveUp) { thrust(); } } void thrust() { vy -= 0.2; // 向上推力,抵消重力实现上升 }
3. 碰撞检测与着陆重启逻辑缺失
原代码的碰撞判断边界错误,而且没有检测是否落在红色着陆区,也没有重启游戏的逻辑。我们修复碰撞检测,并添加resetGame()函数实现重启:
void moveShip() { // 左右边界碰撞 if (posx < 0) { posx = 0; vx = 0; } else if (posx + 50 > width) { posx = width - 50; vx = 0; } // 顶部边界碰撞 if (posy - 10 < 0) { posy = 10; vy = 0; } // 底部着陆检测 if (posy + 25 >= 470) { posy = 470 - 25; // 让飞船刚好落在地面上 // 判断是否在红色着陆区(飞船中心x在200-300之间) if (posx + 25 >= 200 && posx + 25 <= 300) { resetGame(); // 成功着陆,重启游戏 } else { vx = 0; vy = 0; // 着陆失败,停止移动 } } // 更新位置 posx += vx; posy += vy; } void resetGame() { // 重置飞船位置、速度和移动状态 posx = int(random(width - 50)); // 避免飞船超出右边界 posy = 20; vx = 0; vy = 0; moveLeft = moveRight = moveUp = false; }
完整修复后的代码
把所有修改整合起来,最终代码如下:
int posx, posy; float vx, vy; float gravity = 0.05; boolean moveLeft, moveRight, moveUp; void setup() { size(500, 500); background(0); // 初始位置 posx = int(random(width - 50)); // 防止初始位置超出右边界 posy = 20; moveLeft = moveRight = moveUp = false; // 初始速度 vx = vy = 0; // 初始速度设为0,让重力慢慢拉下来 } void draw() { noStroke(); background(0); // 绘制地面和红色着陆区 fill(255, 255, 255); rect(0, 470, width, 30); fill(255, 0, 0); rect(200, 470, 100, 30); // 应用重力 vy += gravity; // 处理按键控制 moveKeys(); // 更新飞船位置和碰撞 moveShip(); // 绘制飞船 drawShip(); } void drawShip() { fill(169, 169, 169); rect(posx, posy, 50, 25); fill(255, 255, 255); rect(posx + 20, posy - 10, 10, 10); fill(105, 105, 105); rect(posx + 20, posy + 25, 10, 5); stroke(255, 255, 255); strokeWeight(2); line(posx + 2, posy + 25, posx + 2, posy + 40); stroke(255, 255, 255); strokeWeight(2); line(posx + 48, posy + 25, posx + 48, posy + 40); } void moveShip() { // 左右边界碰撞 if (posx < 0) { posx = 0; vx = 0; } else if (posx + 50 > width) { posx = width - 50; vx = 0; } // 顶部边界碰撞 if (posy - 10 < 0) { posy = 10; vy = 0; } // 底部着陆检测 if (posy + 25 >= 470) { posy = 470 - 25; // 判断是否在红色着陆区(飞船中心x在200-300之间) if (posx + 25 >= 200 && posx + 25 <= 300) { resetGame(); } else { vx = 0; vy = 0; } } // 更新位置 posx += vx; posy += vy; } void keyPressed() { if (key == CODED) { switch (keyCode) { case UP: moveUp = true; break; case LEFT: moveLeft = true; break; case RIGHT: moveRight = true; break; } } } void keyReleased() { if (key == CODED) { switch (keyCode) { case UP: moveUp = false; break; case LEFT: moveLeft = false; break; case RIGHT: moveRight = false; break; } } } void moveKeys() { if (moveLeft) { vx = -1; } else if (moveRight) { vx = 1; } else { vx = 0; } if (moveUp) { thrust(); } } void thrust() { vy -= 0.2; } void resetGame() { posx = int(random(width - 50)); posy = 20; vx = 0; vy = 0; moveLeft = moveRight = moveUp = false; }
现在你可以运行这段代码,飞船应该能正常左右移动、向上推力抵消重力,并且落在红色区域后自动重启游戏啦!
内容的提问来源于stack exchange,提问作者Fatma
相关产品推荐
相关产品推荐

