You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

碰撞时切换敌人移动方向的逻辑实现求助

碰撞时切换敌人移动方向的逻辑实现求助

嘿,我看了你的代码,问题主要出在方向管理的逻辑和碰撞后的触发机制上,咱们一步步来解决:

问题出在哪儿?

  1. 布尔标志的重置问题:你在AnimationTimer的handle方法里,每次tick都会把当前方向的布尔(比如canUp)设为true,其他全设为false——这就导致哪怕碰撞后你想修改这些标志,下一次循环又会被强制改回去,敌人根本没法切换方向。
  2. 碰撞后没有触发方向切换:你的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;
}

为什么这样改就管用?

  1. 用currentDirection变量替代布尔标志,不会被每次循环重置,切换方向时直接修改这个变量就行,逻辑更清晰。
  2. 碰撞后通过返回值通知Enemy,直接调用switchDirection方法切换到下一个方向,完美实现你要的「碰撞→换方向→继续移动」的逻辑。

如果想调整方向切换的顺序(比如换成随机方向),只要修改switchDirection方法里的逻辑就可以了,非常灵活~

备注:内容来源于stack exchange,提问作者oneHundredd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 06:42:58