Как правильно использовать методы Timer и TimerTask в Java для создания постоянно колеблющегося движущегося объекта на холсте? - PullRequest
0 голосов
/ 02 июля 2011

Я пытаюсь создать 2D-игру, в которой для рисования растровых изображений используется холст, причем эти растровые изображения являются объектами в игре.В настоящее время у меня возникают проблемы с перемещением объекта вперед-назад по экрану (имя объекта является целевым.) Я попытался использовать Timer и TimerTask в качестве средства, чтобы заставить это работать, а также создать новый обработчик, но ничегопохоже на работу.Когда игра запускается, вы можете видеть, как цель перемещается один раз по указанным пикселям (повторяющиеся временные рамки заставляют ее двигаться). Затем приложение вылетает, давая мне сообщение (Извините! - Принудительное закрытие диалога. Что я делаю не так?

MainActivity Code (не очень важно, просто вызывает проблемную GameActivity): пакет 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 голосов
/ 02 июля 2011

Я предложу, и это не использовать TimerTask или Timer для обновления Canvas.

У вас должен быть фоновый поток, который будет обновлять холст, а методы жизненного цикла ваших действий должны управлять запуском и остановкой потока.

Эта ссылка может быть полезна в качестве примера.

...