如何在Android游戏中分离UI和Logic?

时间:2014-11-23 23:42:59

标签: android

我游戏中的动画不稳定,我发现这是因为游戏中的逻辑阻挡了我的GameView中的onDraw()。

但是,我不知道如何将游戏操作与GameView分开。

以下是我的Activity正在运行的类的相关部分:

public class Maze {
  ...
    public boolean keyDown(Object obj, int key) {
    switch (state) {
    // if screen shows title page, keys describe level of expertise
    // create a maze according to the user's selected level
    case Constants.STATE_TITLE:
        if (key >= '0' && key <= '9') {
            break;
        }
        if (key >= 'a' && key <= 'f') {
            break;
        }
        break;
    // if we are currently generating a maze, recognize interrupt signal (ESCAPE key)
    // to stop generation of current maze
    case Constants.STATE_GENERATING:
        if (key == ESCAPE) {
            mazebuilder.interrupt();
            buildInterrupted();
        }
        break;
    // if user explores maze, 
    // react to input for directions and interrupt signal (ESCAPE key)  
    // react to input for displaying a map of the current path or of the overall maze (on/off toggle switch)
    // react to input to display solution (on/off toggle switch)
    // react to input to increase/reduce map scale
    case Constants.STATE_PLAY:
        switch (key) {
        case 'k': case '8':
            walk(1);
            break;
        case 'h': case '4':
            rotate(1);
            break;
        case 'l': case '6':
            rotate(-1);
            break;
        case 'j': case '2':
            walk(-1);
            break;
        case ESCAPE: case 65385:
            if (solving)
                solving = false;
            else
                state = Constants.STATE_TITLE;
            break;
        case ('w' & 0x1f): 
        { 
            setCurrentPosition(px + dx, py + dy) ;
            notifyViewerRedraw() ;
            break;
        }
        case '\t': case 'm':
            mapMode = !mapMode;         
            notifyViewerRedraw() ; 
            break;
        case 'z':
            showMaze = !showMaze;       
            notifyViewerRedraw() ; 
            break;
        case 's':
            showSolution = !showSolution;       
            notifyViewerRedraw() ;
            break;
        case ('s' & 0x1f):
            if (solving)
                solving = false;
            else {
                solving = true;
            }
        break;
        case '+': case '=':
        {
            notifyViewerIncrementMapScale() ;
            notifyViewerRedraw() ; // seems useless but it is necessary to make the screen update
            break ;
        }
        case '-':
            notifyViewerDecrementMapScale() ;
            notifyViewerRedraw() ; // seems useless but it is necessary to make the screen update
            break ;
        }
        break;
    // if we are finished, return to initial state with title screen    
    case Constants.STATE_FINISH:
        state = Constants.STATE_TITLE;
        break;
    } 
    return true;
}

如上所示,Maze对象在用户输入char值时更新其变量。此更新(例如rotate()walk())会依次调用onDraw()

以下是在我的GameView中调用walk()的{​​{1}}方法:

onDraw()

synchronized private void walk(int dir) { if (!checkMove(dir)) return; for (int step = 0; step != 4; step++) { walkStep += dir; gameView.updateGraphics(); } walkFinish(dir); } 中,屏幕被假设被绘制4次,但实际上只在屏幕上绘制了最后一帧。

如何转换for loop,使其分别运行所有逻辑。我尝试使用Maze,但由于每次用户输入字符值时我的Asynctask对象都会更新Maze,因此我收到错误消息{{1}从错误的线程调用。

发布这么多代码的道歉。我曾多次尝试过这个问题,但遗憾的是没有人帮我。如果您需要更多上下文代码,请发表评论。任何帮助将不胜感激!

1 个答案:

答案 0 :(得分:1)

我担心你的循环在gameView.updateGraphics()方法中运行得很快。并且因为updateGraphics发生在后台,所以在第一次调用有机会正确添加之前,它会触发4次。如何用处理程序添加一点延迟?

int step;

for (step = 0; step != 4; step++) 
{
    new Hanlder.postDelayed(new Runnable()
    {
        @Override
        public void run() 
        {
            walkStep += dir;
            gameView.updateGraphics();
        }
    }, 100 * (step + 1));
}

new Hanlder.postDelayed(new Runnable()
{
     @Override
     public void run() 
     {
         walkFinish(dir);
     }
}, 100 * (step + 1));

另外,别忘了将你的dir参数修改为final:

synchronized private void walk(final int dir)