Android 如何延迟使用SurfaceView绘制和设置动画
我正在尝试构建一个简单的Simon Says游戏。我有3个随机放置的位图,它们会将动画从睡眠变为醒来再变为睡眠,我称之为亮起序列,所以当应用程序启动时,每个位图将从睡眠笑脸位图->唤醒笑脸位图-->睡眠笑脸位图转到睡眠笑脸位图,对于随机放置在屏幕上的3个位图中的每一个,笑脸的每次转换之间有1000毫秒的延迟。我得到了一个黑屏,我检查了Android监视器,它说“发送消息给一个死线程上的处理程序”。 我将点亮g的位图命名为。圆点还是好圆点。更新方法将位图图像的状态更新为睡眠位图或唤醒位图,以便根据绘制 屏幕上的位图。我目前正在使用3个随机放置的位图。请帮忙,谢谢。我没有包括我的GoodDot类,它只是一个分配默认睡眠位图笑脸的类,并且有一个方法来检查两个位图是否在屏幕上的同一位置,当然,它跟踪位图在屏幕上的位置,所以(x,y)坐标。请帮忙,谢谢 所以游戏的第一部分是当一个新关卡启动或应用程序打开时(我稍后会担心保存状态),然后一个随机定位和随机分配的3个位图序列将亮起 第2部分:只运行run方法底部的while循环,基本上我将添加检测触摸,让玩家按正确的顺序按下位图以赢得一个关卡 以下是MainActivity类:Android 如何延迟使用SurfaceView绘制和设置动画,android,multithreading,handler,Android,Multithreading,Handler,我正在尝试构建一个简单的Simon Says游戏。我有3个随机放置的位图,它们会将动画从睡眠变为醒来再变为睡眠,我称之为亮起序列,所以当应用程序启动时,每个位图将从睡眠笑脸位图->唤醒笑脸位图-->睡眠笑脸位图转到睡眠笑脸位图,对于随机放置在屏幕上的3个位图中的每一个,笑脸的每次转换之间有1000毫秒的延迟。我得到了一个黑屏,我检查了Android监视器,它说“发送消息给一个死线程上的处理程序”。 我将点亮g的位图命名为。圆点还是好圆点。更新方法将位图图像的状态更新为睡眠位图或唤醒位图,以便根据
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
公共类MainActivity扩展活动{
私有处理器myHandler;
帆布;
油漆;
GameView GameView;
位图;
位图唤醒位图;
最终整型数良好点=3;
静态int curPos=0;//cur g.dot执行其点亮顺序
GoodDot goodDotList[];
int屏幕宽度;
屏幕高度;
//游戏板上某个位置的大小(以像素为单位)
整块大小;
内特诺姆洛克斯威德;
int numBlocksHigh;
静态布尔值isFirstTimeSettingUpGoodDotPosns=false;
静态布尔值isLightUpSequenceFinishedForCurLevel=false;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
gameView=新gameView(此);
canvas=newcanvas();
油漆=新油漆();
myHandler=新处理程序();
配置显示();
setContentView(gameView);
}//结束方法:onCreate
类GameView扩展SurfaceView实现SurfaceHolder.Callback,Runnable{
private SurfaceHolder SurfaceHolder;//这允许我们访问画布,但仍然需要使用canvas类
私有线程读取;
公共游戏视图(上下文){
超级(上下文);
myThread=新线程();
surfaceHolder=getHolder();
surfaceHolder.addCallback(this);
}
@凌驾
已创建的公共空白表面(表面持有人){
myThread.start();
}
@凌驾
公共空间表面变更(表面持有人,
整数格式、整数宽度、整数高度){
//我该在这里输入什么???
}
@凌驾
公共空间表面覆盖(表面覆盖物持有人){
布尔重试=真;
while(重试){
试一试{
myThread.join();
重试=错误;
}捕捉(中断异常e){
e、 printStackTrace();
}
}
isLightUpSequenceFinishedForCurLevel=false;
}
受保护的某物(){
Log.i(“迄今为止的curPos:,”+curPos);
if(surfaceHolder.getSurface().isValid()){
canvas=surfaceHolder.lockCanvas();
如果(isFirstTimeSettingUpGoodDotPosns==false){
//将随机POSN分配给位图
//因为它们不在屏幕上的同一位置!
随机r=新随机();
对于(int i=0;i