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

Android游戏开发:如何实现长按持续向物体施加左右力的控制按钮?

Hey there! Let's figure out how to get that long-press force functionality working for your cube in your Android game. The core issue here is that a standard long-click listener only triggers once—we need a way to keep applying force as long as the user holds the button down. Here are two reliable approaches you can implement right away:

Approach 1: Use Touch Events with Coroutines (Kotlin-Friendly)

This method leverages Android's touch event system and coroutines to create a smooth, lifecycle-safe loop for applying force while the button is held.

// Track if the left button is being pressed
private var isLeftButtonPressed = false
// Adjust this interval to control force application frequency (16ms = ~60fps)
private val forceUpdateInterval = 16L

// Set up left button touch listener
leftControlButton.setOnTouchListener { _, event ->
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            isLeftButtonPressed = true
            // Launch a coroutine to repeatedly apply force
            lifecycleScope.launch {
                while (isLeftButtonPressed) {
                    // Replace this with your actual cube force application logic
                    cubePhysicsBody.applyForce(
                        Vector2(-8f, 0f), // Adjust force magnitude/direction as needed
                        cubePhysicsBody.worldCenter,
                        true
                    )
                    delay(forceUpdateInterval)
                }
            }
            true
        }
        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
            isLeftButtonPressed = false
            true
        }
        else -> false
    }
}

// Repeat for the right button (reverse the force direction)
private var isRightButtonPressed = false
rightControlButton.setOnTouchListener { _, event ->
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            isRightButtonPressed = true
            lifecycleScope.launch {
                while (isRightButtonPressed) {
                    cubePhysicsBody.applyForce(
                        Vector2(8f, 0f),
                        cubePhysicsBody.worldCenter,
                        true
                    )
                    delay(forceUpdateInterval)
                }
            }
            true
        }
        MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
            isRightButtonPressed = false
            true
        }
        else -> false
    }
}

How this works:

  • We listen for ACTION_DOWN (user presses the button) to start the coroutine loop.
  • The loop keeps applying force every forceUpdateInterval milliseconds until isLeftButtonPressed/isRightButtonPressed is set to false.
  • lifecycleScope ensures the coroutine is automatically canceled when the activity/fragment is destroyed, preventing memory leaks.
Approach 2: Use Handler & Runnable (Java or Kotlin)

If you're working with Java or prefer not to use coroutines, this classic Handler-based approach works just as well.

private boolean isLeftPressed = false;
private Handler leftForceHandler = new Handler();
private Runnable leftForceRunnable = new Runnable() {
    @Override
    public void run() {
        if (isLeftPressed) {
            // Apply leftward force to your cube
            cubePhysicsBody.applyForce(
                new Vector2(-8f, 0f),
                cubePhysicsBody.getWorldCenter(),
                true
            );
            // Schedule the next force application
            leftForceHandler.postDelayed(this, 16);
        }
    }
};

// Left button touch listener
leftControlButton.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                isLeftPressed = true;
                leftForceHandler.post(leftForceRunnable);
                return true;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                isLeftPressed = false;
                leftForceHandler.removeCallbacks(leftForceRunnable);
                return true;
            default:
                return false;
        }
    }
});

// Right button implementation is nearly identical—just reverse the force vector

How this works:

  • The Runnable applies force and reschedules itself as long as the button is pressed.
  • ACTION_UP/ACTION_CANCEL stops the loop by setting the pressed flag and removing pending callbacks from the Handler.
Key Notes to Keep in Mind
  • Tweak force values: Adjust the Vector2 magnitude based on your game's physics settings to get the right speed and feel.
  • Prevent leaks: For the Handler approach, be sure to call leftForceHandler.removeCallbacksAndMessages(null) in your activity's onDestroy() method to clean up pending tasks.
  • Smoothness: Using a 16ms interval aligns with a 60fps refresh rate, which will make your cube's movement feel more natural.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:26:18