碰撞时切换敌人移动方向的逻辑实现求助
碰撞时切换敌人移动方向的逻辑实现求助
嘿,我看了你的代码,问题主要出在方向管理的逻辑和碰撞后的触发机制上,咱们一步步来解决:
问题出在哪儿?
- 布尔标志的重置问题:你在
AnimationTimer的handle方法里,每次tick都会把当前方向的布尔(比如canUp)设为true,其他全设为false——这就导致哪怕碰撞后你想修改这些标志,下一次循环又会被强制改回去,敌人根本没法切换方向。 - 碰撞后没有触发方向切换:你的
checkEnemyCollision只是把敌人位置回退,但没有通知敌人“该换方向了”,相当于碰撞只让敌人停下,没告诉它下一步该怎么走。
解决方案:用方向变量替代布尔标志
咱们把四个布尔换成一个方向枚举/变量,这样能清晰管理当前方向,碰撞后直接切换到下一个方向就行,比如按「上→右→下→左」的顺序循环切换。
第一步:修改Enemy类的方向管理
先删掉原来的canUp/canDown/canLeft/canRight这四个布尔,换成方向枚举和当前方向变量:
package application; import java.util.ArrayList; import javafx.animation.AnimationTimer; import javafx.fxml.FXML; import javafx.scene.image.ImageView; import javafx.scene.layout.AnchorPane; import javafx.scene.shape.Rectangle; public class Enemy extends Sprite{ @FXML private ImageView enemy; double x; double y; private int movementVariable = 1; PlayerController playerController; // 定义方向枚举,清晰管理移动方向 private enum Direction { UP, RIGHT, DOWN, LEFT } private Direction currentDirection = Direction.UP; // 默认初始方向向上 public Enemy(ImageView enemy, double x, double y, PlayerController playerController) { super(x,y,enemy); this.enemy = enemy; this.x = x; this.y = y; this.playerController = playerController; } public void moveEnemy(ImageView player, AnchorPane scene, ArrayList<Rectangle> unbreakableObjects) { timer.start(); } AnimationTimer timer = new AnimationTimer() { @Override public void handle(long timestamp) { double currentX = enemy.getLayoutX(); double currentY = enemy.getLayoutY(); // 根据当前方向移动 switch(currentDirection) { case UP: enemy.setLayoutY(enemy.getLayoutY() - movementVariable); break; case RIGHT: enemy.setLayoutX(enemy.getLayoutX() + movementVariable); break; case DOWN: enemy.setLayoutY(enemy.getLayoutY() + movementVariable); break; case LEFT: enemy.setLayoutX(enemy.getLayoutX() - movementVariable); break; } // 检测碰撞:如果碰撞了,回退位置并切换方向 boolean collided = playerController.checkEnemyCollision(currentX, currentY); if(collided) { switchDirection(); } } }; // 切换方向:按上→右→下→左的顺序循环 private void switchDirection() { switch(currentDirection) { case UP: currentDirection = Direction.RIGHT; break; case RIGHT: currentDirection = Direction.DOWN; break; case DOWN: currentDirection = Direction.LEFT; break; case LEFT: currentDirection = Direction.UP; break; } } // 原来的moveUp等方法如果没用可以删掉,或者保留备用 void moveUp() { enemy.setLayoutY(enemy.getLayoutY() - movementVariable); } public void moveDown() { enemy.setLayoutY(enemy.getLayoutY() + movementVariable); } public void moveLeft() { enemy.setLayoutX(enemy.getLayoutX() + movementVariable); } public void moveRight() { enemy.setLayoutX(enemy.getLayoutX() - movementVariable); } }
第二步:修改PlayerController的碰撞检测方法
让checkEnemyCollision返回是否发生了碰撞,这样Enemy才能知道什么时候该切换方向:
public boolean checkEnemyCollision(double currentX, double currentY) { boolean collided = false; if (collisionHandler.checkCollisionUnbreakables(Enemy1, unbreakableObjects)) { Enemy1.setLayoutX(currentX); Enemy1.setLayoutY(currentY); collided = true; } if (collisionHandler.checkCollisionBreakables(Enemy1, breakableObjects)) { Enemy1.setLayoutX(currentX); Enemy1.setLayoutY(currentY); collided = true; } return collided; }
为什么这样改就管用?
- 用
currentDirection变量替代布尔标志,不会被每次循环重置,切换方向时直接修改这个变量就行,逻辑更清晰。 - 碰撞后通过返回值通知Enemy,直接调用
switchDirection方法切换到下一个方向,完美实现你要的「碰撞→换方向→继续移动」的逻辑。
如果想调整方向切换的顺序(比如换成随机方向),只要修改switchDirection方法里的逻辑就可以了,非常灵活~
备注:内容来源于stack exchange,提问作者oneHundredd
相关产品推荐
相关产品推荐

