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

2D无限跑酷游戏实现非触碰式玩家移动技术问询

Hey there! I get exactly what you're dealing with—having to tap directly on your player character to move them makes dodging obstacles a real pain, since you can't see the character clearly when you're tapping. Let's fix that touch control logic so players can steer the character from any spot on the screen.

Fixing the Touch Control for Your 2D Endless Runner

What's Wrong With the Current Code

Looking at your recieveTouch method, the core issue is in the ACTION_DOWN case: you're only enabling movement (movingPlayer = true) if the touch point lands directly on the player's hitbox. That's why players can't control the character unless they tap right on it:

if (!gameOver && player.getRectangle().contains((int) event.getX(), (int) event.getY())) movingPlayer = true;

The Solution: Remove the Hitbox Restriction

We'll modify the code to let any touch on the screen (when the game isn't over) activate movement, and immediately set the player's target position to the touch point. Here's the updated code with comments pointing out the changes:

public boolean recieveTouch(MotionEvent event) { 
    switch (event.getAction()) { 
        case MotionEvent.ACTION_DOWN: 
            int action = event.getAction(); 
            int x = (int) event.getX(); // or getRawX(); 
            int y = (int) event.getY(); 
            int h2 = bitmap2.getHeight(); 
            int w2 = bitmap2.getWidth(); 
            float xRatio2 = (Constants.SCREEN_WIDTH / 2)-( w2 / 2); 
            float yRatio2 = (Constants.SCREEN_HEIGHT / 2)-( h2 / 2) + (Constants.SCREEN_WIDTH/4 + (Constants.SCREEN_WIDTH/6)- Constants.SCREEN_HEIGHT/10); 
            int h55 = bitmap55.getHeight(); 
            int w55 = bitmap55.getWidth(); 
            int h66 = bitmap66.getHeight(); 
            int w66 = bitmap66.getWidth(); 
            float xRatio55 = ((Constants.SCREEN_WIDTH / 4)-( w55 / 4)); 
            float yRatio55 = (((Constants.SCREEN_HEIGHT / 2) + (h55 / 2)) + (Constants.SCREEN_HEIGHT/6)); 
            float xRatio66 = ((Constants.SCREEN_WIDTH / 2)+( w66 / 4) + (Constants.SCREEN_HEIGHT/24)); 
            float yRatio66 = (((Constants.SCREEN_HEIGHT / 2) + (h66 / 2)) + (Constants.SCREEN_HEIGHT/6)); 
            //help 
            int h5 = bitmap4.getHeight(); 
            int w5 = bitmap4.getWidth(); 
            float xRatio5 = ((Constants.SCREEN_WIDTH / 4) - (w5 / 1)); 
            float yRatio5 = (((Constants.SCREEN_HEIGHT / 8) - (h5 / 1))); 
            long pressTime = System.currentTimeMillis(); 

            // --- Modified this section ---
            // Enable movement for any touch when the game is active
            if (!gameOver) {
                movingPlayer = true;
                // Set the player's target position immediately to the touch point
                playerPoint.set(x, y);
            }
            // --- End of modifications ---

            if (gameOver && System.currentTimeMillis() - gameOverTime >= 0) { 
                if (x >= xRatio2 && x < (xRatio2 + bitmap2.getWidth()) && y >= yRatio2 && y < (yRatio2 + bitmap2.getHeight())) { 
                    if (GamePanel.Ad1 == 1) { 
                        MainActivity.click.start(); 
                        MainActivity.mAd = MobileAds.getRewardedVideoAdInstance(mActivityRef.get()); 
                        loadAd(); 
                        MainActivity.mAd.show(); 
                        //Appodeal.show(mActivityRef.get(), Appodeal.REWARDED_VIDEO); 
                    } 
                } 
                if (x >= xRatio55 && x < (xRatio55 + bitmap55.getWidth()) && y >= yRatio55 && y < (yRatio55 + bitmap55.getHeight())) { 
                    MainActivity.click.start(); 
                    reset(); 
                    gameOver = false; 
                    orientationData.newGame(); 
                } 
                if (x >= xRatio66 && x < (xRatio66 + bitmap66.getWidth()) && y >= yRatio66 && y < (yRatio66 + bitmap66.getHeight())) { 
                    MainActivity.click.start(); 
                    SceneManager.ACTIVE_SCENE = 4; 
                    MainActivity.mInterstitialAd.loadAd((new AdRequest.Builder().build())); 
                    MainActivity.mInterstitialAd.show(); 
                    //Appodeal.show(mActivityRef.get(), Appodeal.INTERSTITIAL); 
                    if (GamePanel.YelowBird == 4) { 
                        GamePanel.YelowBird = 2; 
                        GamePanel.RedBird = 1; 
                    } 
                    reset(); 
                    gameOver = false; 
                } 
                if (x >= xRatio5 && x < (xRatio5 + bitmap4.getWidth()) && y >= yRatio5 && y < (yRatio5 + bitmap4.getHeight())) { 
                    if (GamePanel.Help == 0) { 
                        GamePanel.Help = 1; 
                        if (GamePanel.Help == 1) { 
                            MainActivity.click.start(); 
                            orientationData.register(); 
                        } 
                    } else if (GamePanel.Help == 1) { 
                        GamePanel.Help = 0; 
                        if (GamePanel.Help == 0) { 
                            MainActivity.click.start(); 
                            orientationData.pause(); 
                        } 
                    } 
                } 
                return true; 
            } 
            break; 
        case MotionEvent.ACTION_MOVE: 
            if (GamePanel.NinjaBird == 4) { 
                if (!gameOver) playerPoint.set((int) event.getX(), (int) event.getY()); 
            } else { 
                // Optional: Remove the movingPlayer check here to make movement even more responsive
                if (!gameOver) playerPoint.set((int) event.getX(), (int) event.getY());
            } 
            break; 
        case MotionEvent.ACTION_UP: 
            movingPlayer = false; 
            break; 
    } 
    return false; 
}

Extra Tips for Polish

  • If you don't want the player to jump instantly to the touch point, you can calculate a direction vector between the player's current position and the touch point, then move the player smoothly toward that direction each frame.
  • Consider adding a small dead zone around the edges of the screen to prevent accidental touches from triggering movement.
  • If you want the player to keep moving in a direction until the touch ends, you can store the movement direction on ACTION_DOWN instead of updating the target position on ACTION_MOVE.

With this change, players can now control the character from any spot on the screen, keeping the player visible while dodging obstacles!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:34:17