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

JavaFX开发植物大战僵尸:多线程高效碰撞检测方案咨询

Fixing Collision Detection Lag in Your JavaFX Plants vs. Zombies Project

Hey there! I’ve been where you are—trying to get collision detection right in a JavaFX game without grinding the whole thing to a halt. Let’s fix that inefficient infinite loop and get your zombies and lawnmowers interacting smoothly without the lag.

The Problem with Your Current Approach

That while(true) loop you’re using is a total CPU hog. It runs nonstop, gobbling up 100% of a core’s resources without any breaks. Even though zombies take 20+ seconds to reach the lawnmower, the loop doesn’t care—it just keeps churning through collision checks every millisecond, leaving no room for the JavaFX UI thread to update. That’s exactly why you’re seeing stutters and freezes.

Better Solutions to Try

1. Use JavaFX’s AnimationTimer (Best Fit for Game Loops)

JavaFX’s built-in AnimationTimer is made exactly for this kind of game-related per-frame logic. It triggers its handle() method once every frame (synced with the UI’s render cycle), so you only run collision checks when the screen is actually updating—no wasted cycles.

Here’s how to adapt your code:

// Add a flag to each Zombie to prevent repeated collision triggers (optional but critical)
public class Zombie extends Node {
    private boolean isCollidingWithMower = false;
    // Getters and setters for the flag
    public boolean isCollidingWithMower() { return isCollidingWithMower; }
    public void setCollidingWithMower(boolean value) { isCollidingWithMower = value; }
    // Rest of your Zombie code...
}

// Set up the collision timer
AnimationTimer collisionDetector = new AnimationTimer() {
    @Override
    public void handle(long timestamp) {
        // Only check zombies in the same row as the lawnmower
        for (Zombie z : zombies[0]) {
            // First do a quick bounding box check to avoid expensive Shape.intersect calls
            Bounds zombieBounds = z.getBoundsInParent();
            Bounds mowerBounds = mowers[0].getBoundsInParent();
            
            if (zombieBounds.intersects(mowerBounds)) {
                // Now do precise shape intersection
                Shape intersection = Shape.intersect(z, mowers[0]);
                if (intersection != null && !intersection.getBoundsInLocal().isEmpty()) {
                    // Only trigger collision if we haven't already for this frame
                    if (!z.isCollidingWithMower()) {
                        mowers[0].takeHit(1);
                        z.takeHit(100);
                        z.setCollidingWithMower(true);
                    }
                }
            } else {
                // Reset the flag when no collision is detected
                z.setCollidingWithMower(false);
            }
        }
    }
};

// Start the timer when your level begins
collisionDetector.start();

2. Listen to Zombie Movement Properties

Since you’re using TranslateTransition to move zombies, you could listen to the zombie’s translateX property and only run collision checks when the zombie actually moves. This is more targeted than a per-frame timer:

for (Zombie z : zombies[0]) {
    z.translateXProperty().addListener((obs, oldVal, newVal) -> {
        Bounds zombieBounds = z.getBoundsInParent();
        Bounds mowerBounds = mowers[0].getBoundsInParent();
        
        if (zombieBounds.intersects(mowerBounds)) {
            Shape intersection = Shape.intersect(z, mowers[0]);
            if (intersection != null && !intersection.getBoundsInLocal().isEmpty()) {
                // Handle collision (don't forget the collision flag to avoid spamming)
                if (!z.isCollidingWithMower()) {
                    mowers[0].takeHit(1);
                    z.takeHit(100);
                    z.setCollidingWithMower(true);
                }
            }
        } else {
            z.setCollidingWithMower(false);
        }
    });
}

Key Optimizations to Remember

  • Bounding Box First: Always do a quick axis-aligned bounding box check before using Shape.intersect—it’s way faster and eliminates most impossible collision cases upfront.
  • Collision Flags: Adding a boolean flag to each zombie prevents your takeHit() methods from being called hundreds of times per second while the collision is active.
  • Kill the Old Loop: Make sure you stop or never start that original while(true) loop—it’s the root cause of your performance issues.

Quick Note on Your Zombie Movement Code

Your current TranslateTransition setup looks solid, but just remember that any long-running tasks (like Thread.sleep() or CountDownLatch.await()) should be run on a background thread, not the JavaFX UI thread. You’re already doing that, which is great—keep it up!

内容的提问来源于stack exchange,提问作者Jolly Roger

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:03:03