0

我现在正在编写一个 Android 游戏,我需要一些帮助来解决屏幕上墙壁的碰撞问题。当我在顶部和右侧拖动球时,它能够与墙壁发生碰撞,但是当我更快地拖动它时,它能够在墙壁上重叠

public boolean onTouchEvent(MotionEvent event) {
            int x = (int) event.getX();
            int y = (int) event.getY();
            switch (event.getAction()) {
            // if the player moves
            case MotionEvent.ACTION_MOVE: {
                if (playerTouchRect.contains(x, y)) {
                    boolean left = false;
                    boolean right = false;
                    boolean up = false;
                    boolean down = false;
                    boolean canMove = false;
                    boolean foundFinish = false;
                    if (x != pLastXPos) {
                        if (x < pLastXPos) {
                            left = true;
                        } else {
                            right = true;
                        }
                        pLastXPos = x;
                    }
                    if (y != pLastYPos) {
                        if (y < pLastYPos) {
                            up = true;
                        } else {
                            down = true;
                        }
                        pLastYPos = y;
                    }

                    plCellRect = getRectFromPos(x, y);
                    newplRect.set(playerRect);
                    newplRect.left = x - (int) (playerRect.width() / 2);
                    newplRect.right = x + (int) (playerRect.width() / 2);
                    newplRect.top = y - (int) (playerRect.height() / 2);
                    newplRect.bottom = y + (int) (playerRect.height() / 2);
                    int currentRow = 0;
                    int currentCol = 0;
                    currentRow = getRowFromYPos(newplRect.top);
                    currentCol = getColFromXPos(newplRect.right);



                    if(!canMove){
                    canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] == Cell.wall;
                    canMove =true;
                    }
                    finishTest = mapManager.getCurrentTile().pMaze[currentRow][currentCol];
                    foundA = finishTest == Cell.valueOf(letterNotGet + "");



                    canMove = mapManager.getCurrentTile().pMaze[currentRow][currentCol] != Cell.wall;
                    canMove = (finishTest == Cell.floor || finishTest == Cell.pl) && canMove;
                    if (canMove) {
                        invalidate();
                        setTitle();
                    }
                    if (foundA) {
                        mapManager.getCurrentTile().pMaze[currentRow][currentCol] = Cell.floor;
                        //  finishTest
                        letterGotten.add(letterNotGet);
                        playCurrentLetter();
                        /*sounds.play(sExplosion, 1.0f, 1.0f, 0, 0, 1.5f);*/
                        foundS = letterNotGet == 's';
                        letterNotGet++;
                    }if(foundS){
                        AlertDialog.Builder builder = new AlertDialog.Builder(mainActivity);
                        builder.setTitle(mainActivity.getText(R.string.finished_title));
                        LayoutInflater inflater = mainActivity.getLayoutInflater();
                        View view = inflater.inflate(R.layout.finish, null);
                        builder.setView(view);
                        View closeButton =view.findViewById(R.id.closeGame);
                        closeButton.setOnClickListener(new OnClickListener() {
                            @Override
                            public void onClick(View clicked) {
                                if(clicked.getId() == R.id.closeGame) {
                                    mainActivity.finish();
                                }
                            }
                        });
                        AlertDialog finishDialog = builder.create();
                        finishDialog.show();
                    } 
                    else {
                        Log.d(TAG, "INFO: updated player position");
                        playerRect.set(newplRect);
                        setTouchZone();
                        updatePlayerCell();
                    }
                } // end of (CASE) if playerTouch
                break;
            } // end of (SWITCH) Case motion
            }//end of Switch
            return true;
        }//end of TouchEvent
        private void finish() {
            // TODO Auto-generated method stub
        }
        public int getColFromXPos(int xPos) {
            val = xPos / (pvWidth / mapManager.getCurrentTile().pCols);
            if (val == mapManager.getCurrentTile().pCols) {
                val = mapManager.getCurrentTile().pCols - 1;
            }
            return val;
        }
        /**
         * Given a y pixel position, return the row of the cell it is in This is
         * used when determining the type of adjacent Cells.
         * 
         * @param yPos
         *            y position in pixels
         * @return The cell this position is in
         */
        public int getRowFromYPos(int yPos) {
            val = yPos / (pvHeight / mapManager.getCurrentTile().pRows);
            if (val == mapManager.getCurrentTile().pRows) {
                val = mapManager.getCurrentTile().pRows - 1;
            }
            return val;
        }
        /**
         * When preserving the position we need to know which cell the player is in,
         * so calculate it from the centre on its Rect
         */
        public void updatePlayerCell() {
            plCell.x = (playerRect.left + (playerRect.width() / 2))
                    / (pvWidth / mapManager.getCurrentTile().pCols);
            plCell.y = (playerRect.top + (playerRect.height() / 2))
                    / (pvHeight / mapManager.getCurrentTile().pRows);
            if (mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] == Cell.floor) {
                for (int row = 0; row < mapManager.getCurrentTile().pRows; row++) {
                    for (int col = 0; col < mapManager.getCurrentTile().pCols; col++) {
                        if (mapManager.getCurrentTile().pMaze[row][col] == Cell.pl) {
                            mapManager.getCurrentTile().pMaze[row][col] = Cell.floor;
                            break;
                        }
                    }
                }
                mapManager.getCurrentTile().pMaze[plCell.y][plCell.x] = Cell.pl;
            }
        }
        public Rect getRectFromPos(int x, int y) {
            calcCell.left = ((x / cellWidth) + 0) * cellWidth;
            calcCell.right = calcCell.left + cellWidth;
            calcCell.top = ((y / cellHeight) + 0) * cellHeight;
            calcCell.bottom = calcCell.top + cellHeight;
            Log.d(TAG, "Rect: " + calcCell + " Player: " + playerRect);
            return calcCell;
        }
        public void setPlayerRect(Rect newplRect) {
            playerRect.set(newplRect);
        }
        private void setTouchZone() {
            playerTouchRect.set(
                    playerRect.left - playerRect.width() / TOUCH_ZONE,

                    playerRect.top - playerRect.height() / TOUCH_ZONE,
                    playerRect.right + playerRect.width() / TOUCH_ZONE,
                    playerRect.bottom + playerRect.height() / TOUCH_ZONE);
        }
        public Rect getPlayerRect() {
            return playerRect;
        }
        public Point getPlayerCell() {
            return plCell;
        }
        public void setPlayerCell(Point cell) {
            plCell = cell;
        }
    }*
4

1 回答 1

0

这是一个架构问题。你可以在这里阅读更多关于它的信息。

从本质上讲,您的物理模拟(尽可能简单)与您的帧率(上限为 60fps)耦合。任何发生速度快于 60Hz 的事件都无法准确处理,因此您的错误。

解决方案是在独立线程上运行碰撞检测,并以 60fps 的速度绘制它计算的状态。

另外,请查看引用同一篇文章的这些游戏开发问题。

于 2013-08-01T10:53:56.177 回答