如何正确使用Java中的Timer和TimerTask方法在画布上创建一个不断振荡的移动对象?

时间:2011-07-02 04:13:13

标签: java android animation canvas timertask

我正在尝试创建一个使用画布绘制位图的2D游戏,这些位图是游戏中的对象。目前,我遇到了在屏幕上来回移动对象的问题(对象的名称是目标。)我尝试使用Timer和TimerTask作为使其工作的方法,以及创建一个新的Handler,但没有似乎工作。当游戏运行时,您可以看到目标移动一次超过指定的像素(这是一个重复的时间使其移动。)然后应用程序崩溃给我(抱歉! - 强制关闭对话框。我做错了什么?

MainActivity Code(不是很重要,只是触发有问题的GameActivity):     package app.AngryCannonShooterActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.Window;
import android.view.View.*;
import android.widget.Button;




public class MainActivity extends Activity {

    private OnClickListener OptionsButtonListener = new OnClickListener() {
        public void onClick(View v) {
    Intent intent = new Intent(MainActivity.this, OptionsActivity.class);
        MainActivity.this.startActivity(intent);
        }
};
        private OnClickListener HelpButtonListener = new OnClickListener() {
        public void onClick(View v) {
    Intent intent2 = new Intent(MainActivity.this, HelpActivity.class);
        MainActivity.this.startActivity(intent2);
        }
};
    private OnClickListener LeaveButtonListener = new OnClickListener() {
        public void onClick(View v) {
    finish();   
        }
};

    private OnClickListener PlayButtonListener = new OnClickListener() {
        public void onClick(View v) {
    Intent intent3 = new Intent(MainActivity.this, GameActivity.class);
        MainActivity.this.startActivity(intent3);
    }
};

    private OnClickListener TestButtonListener = new OnClickListener() {
        public void onClick(View v) {
    Intent intent3 = new Intent(MainActivity.this, TestActivity.class);
        MainActivity.this.startActivity(intent3);
    }
};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.main);
        Button OptionsButton = (Button)findViewById(R.id.MainScreenOptionsButton);
        OptionsButton.setOnClickListener(OptionsButtonListener);
        Button LeaveButton = (Button)findViewById(R.id.MainScreenLeaveButton);
        LeaveButton.setOnClickListener(LeaveButtonListener);
        Button HelpButton = (Button)findViewById(R.id.MainScreenInstructionsButton);
        HelpButton.setOnClickListener(HelpButtonListener);
        Button PlayButton = (Button)findViewById(R.id.MainScreenPlayButton);
        PlayButton.setOnClickListener(PlayButtonListener);
        Button TestButton = (Button)findViewById(R.id.TestButtonMainScreen);
        TestButton.setOnClickListener(TestButtonListener);
        }

}

这是我的GameActivity代码:

    package app.AngryCannonShooterActivity;

import java.util.ArrayList;
import java.util.Timer;
import java.util.TimerTask;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.Window;
import android.view.View.*;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.MotionEvent;
import android.view.SurfaceView;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.widget.Button;
import android.widget.LinearLayout;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.content.res.Resources;


public class GameActivity extends Activity {
    //^GameActivity START^
    final Handler timerhandler = new Handler();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    LinearLayout touchspread;
    touchspread = new LinearLayout(this);
    setContentView(new Panel(this));
    touchspread.requestLayout();

    }

class Panel extends SurfaceView implements SurfaceHolder.Callback {
    //^Panel Class START^

    private Bitmap cannon;
    private Bitmap launchbutton;
        private Bitmap leftbutton;
    private Bitmap rightbutton;
    private Bitmap target;
    private ViewThread mThread;
    private int mX;
    private int launchbuttonxvalue;
    private int launchbuttonyvalue;
    private int leftbuttonxvalue;
    private int leftbuttonyvalue;
    private int rightbuttonxvalue;
    private int rightbuttonyvalue;
    private int scoretextviewxvalue;
    private int scoretextviewyvalue;
    private int cannonincrementmovement;
    private int score;
    private int cannonrestrictionpoint;
    private int cannonresetpoint;
    private int targetxvalue;
    private int targetyvalue;
    private int targetmovementincrementvalue;

    public Panel (Context context) {
        super(context);
        cannon = BitmapFactory.decodeResource(getResources(),        R.drawable.testcannon);
        launchbutton = BitmapFactory.decodeResource(getResources(), R.drawable.launchbutton);
        leftbutton = BitmapFactory.decodeResource(getResources(), R.drawable.leftbutton);
        rightbutton = BitmapFactory.decodeResource(getResources(), R.drawable.rightbutton);
        target = BitmapFactory.decodeResource(getResources(), R.drawable.testtarget);
        getHolder().addCallback(this);
        mThread = new ViewThread(this);
    }
    public Canvas canvas;
    @Override
    public void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        canvas.drawColor(Color.BLACK);
        paint.setColor(Color.YELLOW);
        paint.setTypeface(Typeface.DEFAULT_BOLD);
        paint.setAlpha(30+20*1);
        canvas.drawPaint(paint);
        paint.setTextSize(20);
        canvas.drawText("Score: "+score, scoretextviewxvalue, scoretextviewyvalue, paint);
        canvas.drawBitmap(launchbutton, launchbuttonxvalue, launchbuttonyvalue, null);
        canvas.drawBitmap(cannon, mX, (float) (canvas.getHeight()-(launchbutton.getHeight()*4.2)), null);
        canvas.drawBitmap(leftbutton, leftbuttonxvalue, leftbuttonyvalue, null);
        canvas.drawBitmap(rightbutton, rightbuttonxvalue, rightbuttonyvalue,null);
        canvas.drawBitmap(target, targetxvalue, targetyvalue, null);
        launchbuttonxvalue = (int) ((canvas.getWidth()-launchbutton.getWidth())/2);
        launchbuttonyvalue = (int) (canvas.getHeight()*0.92);
        leftbuttonxvalue = (int) (0);
        leftbuttonyvalue = (int) (canvas.getHeight()*0.9);
        rightbuttonxvalue = (int) (canvas.getWidth()*0.91);
        rightbuttonyvalue = (int) (canvas.getHeight()*0.9);
        scoretextviewxvalue = (int) ((canvas.getWidth())/1.4);
        scoretextviewyvalue = (int) ((canvas.getHeight())/15);
        cannonincrementmovement = (int) (10);
        score = (int) (0);
        cannonrestrictionpoint = (int) ((canvas.getWidth())-cannon.getWidth());
        cannonresetpoint = (int) ((canvas.getWidth()*0.9));
        targetxvalue = (int) (0);
        targetyvalue = (int) ((canvas.getHeight())/2.2);
        targetmovementincrementvalue = (int) (5);
        final Runnable timerrunnable = new Runnable() {
            public void run() {
                movetarget();
            }
        };
        Timer timer = new Timer();
        TimerTask task = new TimerTask() {
            @Override
            public void run() {
            timerhandler.post(timerrunnable);
            }};
        timer.scheduleAtFixedRate(task, 200, 1000);
    } 

    public int getOpacity() {
             return 0;
     }

     public void setAlpha(int alpha) {

     }


     public void setColorFilter(ColorFilter cf) {

     }


    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    public void surfaceCreated(SurfaceHolder holder) {
        if (!mThread.isAlive()) {
            mThread = new ViewThread(this);
            mThread.setRunning(true);
            mThread.start();
        }
    }

    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mThread.isAlive()) {
            mThread.setRunning(false);
        }
    }

    public void checkgridleftbutton() {
        if (mX < 0) {
        mX = (int) (0);
        }
    }

    public void checkgridrightbutton() {
        if (mX > cannonrestrictionpoint) {
            mX = (int) (cannonresetpoint);
        }
    }
    public void checktargetlocation() {
        if (targetxvalue <= -1) {
            invertdirection();
        }
        if (targetxvalue >= (canvas.getWidth()-target.getWidth())); {
            invertdirection();
        }
    }

    public void invertdirection() {
        targetmovementincrementvalue = targetmovementincrementvalue*-1;
    }

    public void movetarget() {
    targetxvalue = (int) (targetxvalue + targetmovementincrementvalue);
    checktargetlocation();
    }

    public class ViewThread extends Thread {
        //^ViewThread Class START^
        private Panel mPanel;
        private SurfaceHolder mHolder;
        private boolean mRun = false;

        public ViewThread(Panel panel) {
            mPanel = panel;
            mHolder = mPanel.getHolder();
        }

        public void setRunning(boolean run) {
            mRun = run;
        }

        @Override
        public void run() {
            Canvas canvas = null;
            while (mRun) {
                canvas = mHolder.lockCanvas();
                if (canvas != null) {
                    mPanel.onDraw(canvas);
                    mHolder.unlockCanvasAndPost(canvas);
                }
            }
        }
    }
    //^ViewThread Class END^
    @Override
    public boolean onTouchEvent(MotionEvent event){
        int action = event.getAction();
        int x = (int) event.getX();
        int y = (int) event.getY();
        switch(action){
        case MotionEvent.ACTION_DOWN:
            if (x >= launchbuttonxvalue && x < (launchbuttonxvalue + launchbutton.getWidth())
                && y >= launchbuttonyvalue && y < (launchbuttonyvalue + launchbutton.getHeight())) {
            finish();
        }
        if (x >= leftbuttonxvalue && x < (leftbuttonxvalue + leftbutton.getWidth())
                && y >= leftbuttonyvalue && y < (leftbuttonyvalue + leftbutton.getHeight())) {
            mX = mX - cannonincrementmovement;
            checkgridleftbutton();
        }
        if (x >= rightbuttonxvalue && x < (rightbuttonxvalue + rightbutton.getWidth())
                && y >= rightbuttonyvalue && y < (rightbuttonyvalue + rightbutton.getHeight())) {
            mX = mX + cannonincrementmovement;
            checkgridrightbutton();
        }
        break;
    }
    return super.onTouchEvent(event);
}
//^Panel Class END^

    }
}
//^GameActivity Class END^

1 个答案:

答案 0 :(得分:0)

我会提供一个建议,即不使用TimerTaskTimer来更新Canvas

你应该有一个后台线程来更新画布,你的活动生命周期方法应该管理启动和停止线程。

This link可能会有所帮助。