0

我正在尝试解决这个问题超过 2 天,并且已经变得非常绝望。

我想为安卓写一个“跳棋式”棋盘游戏。游戏引擎本身还算完整,但我在更新视图时遇到了问题。

我写了一个小示例类来演示我的问题:

public class GameEngineView extends View {

private static final String TAG = GameEngineView.class.getSimpleName();

private int px;
private int py;
private int cx;
private int cy;

private boolean players_move;
private int clickx;
private int clicky;

Random rgen;

private RefreshHandler mRedrawHandler = new RefreshHandler();

class RefreshHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {            
        GameEngineView.this.update();
        GameEngineView.this.invalidate();
        Log.d(TAG, "invalidate()");            
    }

    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
};

public GameEngineView(Context context) {
    super(context);
    setFocusable(true);
    players_move = true;
    rgen = new Random();
}

public void update() {
    updateGame();
    Log.d(TAG, "update -> sleep handler");
    mRedrawHandler.sleep(100);
}

public void updateGame() {
    if(players_move) {
        px = clickx;
        py = clicky;
    } else {
        calcAIMove();
        switchMove();
    }        
}

public void switchMove() {
    players_move = !players_move;
}

public void calcAIMove() {
    for(int i = 0; i < 20000; i++) {
        cx = rgen.nextInt(getWidth());
        cy = rgen.nextInt(getHeight());
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.d(TAG, "event");
    int eventaction = event.getAction();
    if(eventaction == MotionEvent.ACTION_DOWN) {
        Log.d(TAG, "action_down");
        clickx = (int) event.getX();
        clicky = (int) event.getY();
        switchMove();
        update();
    }
    return super.onTouchEvent(event);
}

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    Paint green = new Paint();
    green.setColor(Color.GREEN);
    Paint red = new Paint();
    red.setColor(Color.RED);
    canvas.drawColor(Color.BLACK);
    canvas.drawCircle(px, py, 25, green);
    canvas.drawCircle(cx, cy, 25, red);
}

}

函数 calcAIMove() 只是消耗时间来模拟棋盘游戏中位置的真实评估。

现在我的问题是:如果玩家点击(移动),则在 ai 移动计算完成时首先绘制绿球。所以这两个动作是同时绘制的。

我想知道如何做到这一点:-玩家点击-绿色球被绘制-AI计算-红色球被绘制-等等..

在网上搜索时,我发现了很多游戏循环示例,但它们都需要一个持续轮询的线程。没有这个应该是可能的,因为整个程序是按顺序运行的。对吗?

希望得到建议。

谢谢,戴夫

4

3 回答 3

2

以下是您的游戏的运行方式:

  1. 用户采取行动
  2. 游戏视图已更新
  3. 游戏切换到 CPU 的回合
  4. sleep 模拟 CPU 玩家的思维(如果移动计算很简单)
  5. 计算 CPU 的移动
  6. 游戏视图已更新
  7. 游戏切换到玩家的回合

在这样的回合制游戏中,不需要不断的轮询。您唯一应该睡觉的地方是第 4 步,因此您可以将其从其他区域移除(不需要旧update()方法,它只是延迟调用updateGame())。

实现这一点的一种方法是简单地延迟调用calcAIMove()switchMove()通过将其放入 aRunnable和 usingHandler.postDelayed()或类似方法。

我看不出你是如何在轮到 CPU 时禁用触摸事件的,如果switchMove()并且update()仍在被调用,这可能会导致许多其他问题......

于 2011-01-13T00:29:40.943 回答
0

在您的游戏循环中,您可以使用 TimerTask 的实例来确保 greenBall 和其他绘图任务之间的一定延迟。Snake 和 LunarLander 等游戏教程是关于何时以及是否需要使视图无效的很好参考。希望这有所帮助!

于 2011-01-13T00:01:14.657 回答
0

好的,所以 antonyt 提供的答案帮助我解决了这个问题。我为其他感兴趣的人提供了更正的代码。

public class GameEngineView extends View {

private static final String TAG = GameEngineView.class.getSimpleName();

private int px;
private int py;
private int cx;
private int cy;

private boolean players_move;
private int clickx;
private int clicky;

Random rgen;

/**
 * Create a simple handler that we can use to cause animation to happen.  We
 * set ourselves as a target and we can use the sleep()
 * function to cause an update/invalidate to occur at a later date.
 */
private RefreshHandler mRedrawHandler = new RefreshHandler();

class RefreshHandler extends Handler {
    @Override
    public void handleMessage(Message msg) {
        GameEngineView.this.update();
    }

    public void sleep(long delayMillis) {
        this.removeMessages(0);
        sendMessageDelayed(obtainMessage(0), delayMillis);
    }
};

public GameEngineView(Context context) {
    super(context);
    setFocusable(true);
    players_move = true;
    rgen = new Random();
}

public void update() {
    if(players_move) {
        Log.d(TAG, "new player x");
        px = clickx;
        py = clicky;
        GameEngineView.this.invalidate();
        switchMove();
        mRedrawHandler.sleep(100);
    } else {
        Log.d(TAG, "new ai x");
        calcAIMove();
        GameEngineView.this.invalidate();
        switchMove();            
    }

    Log.d(TAG, "update -> sleep handler");        
}


public void switchMove() {
    players_move = !players_move;
}

public void calcAIMove() {
    for(int i = 0; i < 100000; i++) {
        cx = rgen.nextInt(getWidth());
        cy = rgen.nextInt(getHeight());
    }
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.d(TAG, "event");
    int eventaction = event.getAction();
    if(players_move && eventaction == MotionEvent.ACTION_DOWN) {
        Log.d(TAG, "action_down");
        clickx = (int) event.getX();
        clicky = (int) event.getY();
        update();
    }
    return super.onTouchEvent(event);
}

@Override
public void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawColor(Color.BLACK);
    Paint green = new Paint();
    green.setColor(Color.GREEN);
    Paint red = new Paint();
    red.setColor(Color.RED);

    canvas.drawCircle(px, py, 25, green);
    canvas.drawCircle(cx, cy, 25, red);
}

}

于 2011-01-13T08:26:28.720 回答