如何使用延迟

时间:2017-07-16 03:12:55

标签: android multithreading handler

我正在尝试构建一个简单的Simon Says游戏。我有3个随机放置的位图,它们会将动画从睡眠状态改为睡眠状态,我称之为点亮序列,所以当应用程序启动时,每个位图都会从睡眠笑脸位图 - >唤醒笑脸位图 - >睡眠面位图,并且对于随机放置在屏幕上的3个位图中的每一个,在笑脸的每次转换之间存在1000ms的延迟。我得到一个黑屏,我检查Android监视器,它说“在死线程上向处理程序发送消息”。 我将我的位图命名为点亮g。点或好点。 update方法将位图图像的状态更新为睡眠位图或唤醒位图以进行绘制 屏幕上的位图。我目前正在使用3个随机放置的位图。请帮助,欣赏它。我没有包含我的GoodDot类,它只是一个分配默认睡眠位图笑脸的类,并且有一种方法可以检查2个位图是否没有落在屏幕上的同一位置,当然跟踪位图在屏幕上的位置所以( x,y)坐标。请帮助,欣赏它。

因此,游戏的第1部分是新级别开始或应用程序打开时(我会担心以后保存状态)然后随机定位并随机分配3个位图的序列将亮起

第2部分:只是在run方法的底部运行while循环,基本上我会添加检测触摸,让玩家按正确的顺序按位图来赢得一个级别。

这是MainActivity类:

public class MainActivity extends Activity {

private Handler myHandler;
Canvas canvas;
Paint paint;
GameView gameView;
Bitmap restBitmap;
Bitmap awakeBitmap;
final int NUM_GOOD_DOTS = 3;
static int curPos = 0;//cur g. dot doing its light up sequence
GoodDot goodDotList[];

int screenWidth;
int screenHeight;
//The size in pixels of a place on the game board
int blockSize;
int numBlocksWide;
int numBlocksHigh;

static boolean isFirstTimeSettingUpGoodDotPosns = false;
static boolean isLightUpSequenceFinishedForCurLevel = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    gameView = new GameView(this);
    canvas = new Canvas( );
    paint = new Paint ( );
    myHandler = new Handler();
    configureDisplay();
    setContentView(gameView);

}//END METHOD: onCreate

class GameView extends SurfaceView implements SurfaceHolder.Callback, Runnable {

    private SurfaceHolder surfaceHolder;//this lets us access the canvas but still need to use Canvas class
    private Thread myThread;

    public GameView(Context context) {
        super(context);
        myThread = new Thread();
        surfaceHolder = getHolder();
        surfaceHolder.addCallback(this);
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        myThread.start();
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder,
                               int format, int width, int height) {
        // What do I enter here???
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        boolean retry = true;
        while (retry) {
            try {
                myThread.join();
                retry = false;
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        isLightUpSequenceFinishedForCurLevel = false;
    }

    protected void drawSomething ( ) {
        Log.i ("curPos so far:", "" + curPos );

        if (surfaceHolder.getSurface().isValid() ) {
            canvas = surfaceHolder.lockCanvas();

            if (isFirstTimeSettingUpGoodDotPosns == false) {

                //assign random posns to bitmaps
                //  as they are NOT on same spot on screen!
                Random r = new Random();
                for (int i = 0; i < NUM_GOOD_DOTS; i++) {
                    goodDotList[i] = new GoodDot(1, 1, restBitmap);
                    goodDotList[i].setGoodDotX((r.nextInt(3) + 1) * blockSize);
                    goodDotList[i].setGoodDotY((r.nextInt(3) + 1) * blockSize);
                }

                //this method ensures no bitmaps land on same position 
                //   on screen
                gameView.assignProperPosnForGoodDots();

                isFirstTimeSettingUpGoodDotPosns = true;
            }

            canvas.drawColor(Color.BLACK);//the background
            paint.setColor(Color.argb(255, 255, 255, 255));
            paint.setStrokeWidth(3);

            // for loop to draw all g. dots
            for (int i = 0; i < NUM_GOOD_DOTS; i++) {

                canvas.drawBitmap(goodDotList[i].getBitmap(),
                        goodDotList[i].getGoodDotX(), goodDotList[i].getGoodDotY(), paint);
            }

            //this method called is only for testing
            drawGrid(canvas);
            surfaceHolder.unlockCanvasAndPost(canvas);
    }//END IF BLOCK: For valid surfaceHolder
 }//END METHOD: drawSomething

    //this method is only for testing to see the grid that each bitmap is inside a block
    private void drawGrid ( Canvas canvas ) {

        //var to draw horizontal line part of grid
        float rowStartX = 0; float rowStartY = 0;
        float rowEndX = screenWidth;  float rowEndY = 0;

        //var to draw vertical line part of grid
        int colStartX = 0; int colStartY = 0;
        int colEndX = 0;  int colEndY = screenHeight;

        // Log.d("NUM BLOCKS HIGH", "Value:" + numBlocksHigh );

        //draw the horizontal lines
        for ( int i  = 0; i < numBlocksHigh; i++ ) {
            canvas.drawLine ( rowStartX, rowStartY, rowEndX, rowEndY , paint );
            rowStartY += blockSize;
            rowEndY += blockSize;
        }

        //draw the vertical lines
        for ( int i  = 0; i < numBlocksWide; i++ ) {
            canvas.drawLine ( colStartX, colStartY, colEndX, colEndY , paint );
            colStartX += blockSize;
            colEndX += blockSize;
        }
    }//END METHOD: drawGrid

    //Each g. dot goes thru 3 states: rest, light up/awake, rest
    public void update() {

        switch ( goodDotList [ curPos ].getGoodDotState() ) {
            case 1:
                goodDotList[ curPos ].setBitmap( restBitmap );
                break;
            case 2:
                goodDotList[ curPos ].setBitmap( awakeBitmap );
                break;
            case 3:
                goodDotList[ curPos ].setBitmap( restBitmap );
                break;
            default:
                break;
        }

        //Go to next g. dot once 3 states finished for a given g. dot
        if ( goodDotList [ curPos ].getGoodDotState() > 3 ) {
            curPos++;
        }
        else {
            goodDotList [ curPos ].setGoodDotState(
                    goodDotList [ curPos ].getGoodDotState() + 1 );
        }
    }//END METHOD: update

    //this method makes sure no GOOD DOTS land on same spot
    public void assignProperPosnForGoodDots ( ) {

        int curGdotPos = 0;
        Random rand = new Random ();
        boolean isHitFound = false;

        while ( curGdotPos < NUM_GOOD_DOTS ) {

            for (int j  = curGdotPos + 1; j < NUM_GOOD_DOTS; j++ ) {

                if ( goodDotList [ curGdotPos ].checkForHit( NUM_GOOD_DOTS, goodDotList [ j ] ) ) {
                    goodDotList[curGdotPos].setGoodDotX( (rand.nextInt(3) + 1) * blockSize  )  ;
                    goodDotList[curGdotPos].setGoodDotY( ( rand.nextInt(3) + 1) * blockSize  );
                    isHitFound = true;
                    break;
                }
            }//END INNER FOR LOOP

            if ( isHitFound ) {
                curGdotPos = 0;
                isHitFound = false;//reset for next round
            }
            else
                curGdotPos++;
        }//END WHILE LOOP
    }//END METHOD: assignProperPosnForGoodDots

    @Override
    public void run() {

        if (curPos < NUM_GOOD_DOTS) {
            Log.i("hi", "hi, more g. dots to light up!");
            gameView.update();
            gameView.drawSomething();
        }
        if ( curPos < NUM_GOOD_DOTS ) {
            myHandler.postDelayed(this, 1000);
        }
        else {
            isLightUpSequenceFinishedForCurLevel = true;
        }

        while ( isLightUpSequenceFinishedForCurLevel )
            gameView.drawSomething( );
    }

}//END INNER CLASS: GameView

/**
 * BELOW are Main Activity Life Cycle Call Back methods!
 */
@Override
protected void onStop() {
    super.onStop();
    Log.d("onStop", "Main Activity's onStop called");
    gameView.surfaceDestroyed( gameView.getHolder() );
    this.finish();
}

@Override
protected void onResume() {
    super.onResume();
    Log.d("onResume", "Main Activity's onResume called");

    gameView = new GameView(this);
    setContentView(gameView);
    gameView.surfaceCreated( gameView.getHolder() );
}

@Override
protected void onPause() {
    super.onPause();
    Log.i("onPause", "Main Activity's onPause called");
    gameView.surfaceDestroyed( gameView.getHolder() );
}

public void configureDisplay() {
    //find out the width and height of the screen
    Display display =
            getWindowManager().getDefaultDisplay();
    Point size = new Point();
    display.getSize(size);
    screenWidth = size.x;
    screenHeight = size.y;

    //Determine the size of each block/place on the game board
    blockSize = screenWidth/10;

    //Determine how many game blocks will fit into the
    //height and width
    //Leave one block for the score at the top
    numBlocksWide = 10;
    numBlocksHigh = ( ( screenHeight ) ) / blockSize;

    //Load and scale bitmaps
    restBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.good_dot_rest_state );
    awakeBitmap = BitmapFactory.decodeResource(getResources(),
            R.drawable.good_dot_light_up_state );

    //scale the bitmaps to match the block size
    restBitmap = Bitmap.createScaledBitmap( restBitmap,
            blockSize  , blockSize , false);
    awakeBitmap = Bitmap.createScaledBitmap( awakeBitmap,
            blockSize , blockSize , false);

    goodDotList = new GoodDot[ NUM_GOOD_DOTS ];

  //initialize g. dots w coordinate (0,0)
    for ( int i = 0; i < NUM_GOOD_DOTS; i++ )
        goodDotList [ i ] = new GoodDot( 0, 0, restBitmap );

}//END METHOD: configureDisplay

}//END CLASS: MainActivity

1 个答案:

答案 0 :(得分:0)

愚蠢的我,我的位图没有从休息的笑脸位图变为清醒的笑脸位图回到休息笑脸图位图的原因是因为在我的位图类中我的setter是多余的,如:public void setBitmap(Bitmap bmp_ ){ this.bmp = this.bmp;} ...应该是:this.bmp = bmp _!