如何使用延迟使用 SurfaceView 进行绘制和动画处理



我正在尝试构建一个简单的Simon Said游戏。我有 3 个随机放置的位图,它们将它们的动画从睡眠更改为醒来再到睡眠,我称之为点亮序列,因此当应用程序启动时,每个位图将从睡眠笑脸位图>唤醒笑脸位图-->睡觉的脸位图,并且随机放置在屏幕上的 3 个位图中的每一个笑脸过渡之间有 1000 毫秒的延迟。我得到一个黑屏,我检查Android监视器,它说"向死线程上的处理程序发送消息"。 我命名了点亮或好点的位图。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

愚蠢的我,我的位图没有从休息笑脸位图更改为清醒笑脸位图回到休息笑脸位图的原因是因为在我的位图类中,我的二传手是多余的,如下所示: 公共无效集位图(位图bmp_){ this.bmp = this.bmp;}...应该是:这个.bmp=bmp_!

最新更新