Android的 - 创造一个乒乓球比赛计时器循环(Android - Creating a Tim

2019-08-31 12:38发布

我有一个乒乓球比赛,我用Java写的,我想将它移植到Android。 (这是我的第一个Android游戏)。

在Java我使用的Timer ,其基本上更新了游戏的值(球/桨位置),然后重画屏幕对象。

我想实现的Android相同的功能,但我得到了一些错误。

我的程序由一个的PongView类,这是游戏的视觉部分,和PongDriverActivity它使用类PongView其观点。 如果我有一个循环的线程无效PongView我得到一个错误,因为线程不能碰观点产生了另一个线程。

我想我需要做某种AsyncTask ,但我不知道如何环路。

什么任何建议将是实现这一目标的最佳方式是什么?

Answer 1:

有很多方法可以做到这一点。 Android提供支持普通的Java Thread对象,你可以使用这些。 您可以搜索(SO)的android game loop ,并可能会发现很多例子。 但是,如果你想尝试AsyncTask ,这里有一个简单的实现:

public class PongView extends View {

    public PongView(Context context) {
        super(context);
    }    
    public void setBallPosition(int x, int y) {
        // relocate the ball graphic
    }    
}

然后,你的活动:

public class PongDriverActivity extends Activity implements OnSeekBarChangeListener {

    private enum GameSpeed { SLOW, MEDIUM, FAST };

    private PongView mGameView;
    private PongDriverTask mWorker;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mGameView = new PongView(this);
        mWorker = new PongDriverTask(GameSpeed.MEDIUM);

        // if you need to pass some data to the worker:
        mWorker.execute("one", "two", "three");  
        // else, declare the AsyncTask's first generic param as Void, and do:
        //mWorker.execute();

        setContentView(mGameView);
    }

    // you would connect this up to a button, to allow the user to stop  
    public void onStopClicked(View sender) {
        if (mWorker.isRunning()) {
            mWorker.stopRunning();
        }
    }

    // you could connect this up to a slider, to allow the user to control the paddle
    public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
        // you may need to convert progress to a y-coordinate
        mWorker.setPaddlePosition(progress);
    }

而且,当时(也许里面PongDriverActivity.java,一个内部类):

private class PongDriverTask extends AsyncTask<String, Integer, Integer> {

    private int mDelay;
    private boolean mRunning = true;
    private int mPaddleY = 0;

    public PongDriverTask(GameSpeed speed) {
        if (speed == GameSpeed.SLOW) {
            mDelay = 100;
        } else if (speed == GameSpeed.MEDIUM) {
            mDelay = 50;
        } else if (speed == GameSpeed.FAST) {
            mDelay = 10;
        }
    }

    public synchronized boolean isRunning() {
        return mRunning;
    }
    public synchronized void stopRunning() {
        mRunning = false;
    }
    public synchronized void setPaddlePosition(int y) {
        mPaddleY = 0;
    }
    private synchronized int getPaddlePosition() {
        return mPaddleY;
    }

    @Override
    protected void onPostExecute(Integer score) {
        super.onPostExecute(score);
        // here you could show a UI that shows the final score
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();

        mGameView.setBallPosition(0, 0);
        // here you could throw up some UI that shows just
        //  before the game really starts
    }

    @Override
    protected void onProgressUpdate(Integer... params) {
        super.onProgressUpdate(params);
        // retrieve updated game coordinates from params
        mGameView.setBallPosition(params[0], params[1]);  // x,y
    }

    @Override
    protected Integer doInBackground(String... args) {
        // If you have some information to pass to the background worker, 
        //  it would be passed in args[0], args[1], etc.
        // It doesn't have to be String data.  you could change the generic 
        //  to take something other than String as the first param, in which
        //  case, doInBackground() would take a variable length list of that
        //  other data type.
        int ballX = 0;
        int ballY = 0;
        int score = 0;

        while (isRunning()) {
            // use your game engine to recalculate the ball position
            //  on this background thread
            int paddleY = getPaddlePosition();
            ballX += 1;
            ballY += 2;
            score++;

            // now, update the UI, which must happen on the UI thread
            publishProgress(ballX, ballY);

            try {
                Thread.sleep(mDelay);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return score;
    }
}

任务的doInBackground()方法会在后台线程中运行,所以你必须不能直接从那里修改UI。 但是,所有其他AsyncTask方法我上面覆盖被称为UI线程上,所以它是安全的,在其中的任何执行UI工作。

此代码假定桨通过搜索栏,你会做你的控制Activity的变化侦听。 其他很多方式做到这一点,太。

我只是实现了一个原油游戏停止机制,你可以钩到一个按钮。 如果你想允许用户暂停和恢复,你可以搜索到的实现暂停/恢复线程,这应该是适用在这里也。 例如:

如何暂停,并从另一个线程恢复Java中的一个线程

更多阅读...

看到这个书面记录的游戏循环的速度进行了一些讨论 ...

也许看看这个讨论,也



文章来源: Android - Creating a Timer loop for a pong game