Android 开发中:Canvas 显示不正确

Android Developing: Canvas not displayed correctly

我是 android 开发的新手,并尝试实现一个简单的游戏,该游戏是通过表面视图和 canvas 实现的。我使用 LunarView 示例作为草稿。

想法是让一个人(通过触摸事件控制移动)和一个跟随他的僵尸。

到目前为止,我有以下 classes(我删除了我认为无用的代码):

1) 主要Activity

public class MainActivity extends ActionBarActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
}
}

2) ZombieView with the innner class ZombieThread and Person (Person 仅用于保存数据需要)

public class ZombieView extends SurfaceView implements SurfaceHolder.Callback {

//Thread Class that performs drawing on Canvas
class ZombieThread extends Thread {

    class Person {
        ...
    }

    private final SurfaceHolder surfaceHolder;
    private ZombieView zombieView;
    private Context context;
    private boolean running = false;

    //Canvas info
    private int mCanvasWidth = 1;
    private int mCanvasHeight = 1;
    private Bitmap mBackgroundImage;
    private final Drawable mHumanImage;
    private final Drawable mZombieImage;
    private Resources res;

    //Game Variables
    double hSpeed = 1;
    double zSpeed = 0.8;
    Person zombie;
    Person human;

    public ZombieThread(SurfaceHolder holder, ZombieView zombie, Context context) {
        this.surfaceHolder = holder;
        this.zombieView = zombie;
        this.context = context;

        this.zombie = new Person(100, 100, hSpeed);
        this.zombie.setRunning(true); //zombie always walks
        this.human = new Person(100, 200, zSpeed);

        res = context.getResources();
        mHumanImage = context.getResources().getDrawable(R.drawable.green_circle);
        mZombieImage = context.getResources().getDrawable(R.drawable.red_circle);
        mBackgroundImage = BitmapFactory.decodeResource(res,R.drawable.background);

    }

    @Override
    public void run() {
        Canvas c = null;
        while (this.running) {

            try {
                c = surfaceHolder.lockCanvas(null);

                synchronized (surfaceHolder) {
                    play();
                    onDraw(c);
                    checkCollision();

                }
            } finally {
                if (c != null) {
                    surfaceHolder.unlockCanvasAndPost(c);
                }
            }
            try {
                sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public void checkCollision() {
        //do something
    }

    public void play() {
        ...
    }

    public void onDraw(Canvas c) {
        //Do your drawing here...
      //  c.drawColor(Color.rgb(10, 0, 0));

        c.drawBitmap(mBackgroundImage, 0, 0, null);
        c.save();

        //draw human and zombie
        int width = mHumanImage.getIntrinsicWidth();
        int height = mHumanImage.getIntrinsicHeight();

        mHumanImage.setBounds((int) human.getX() - (width / 2), (int) human.getY() - (height / 2),
                (int) human.getX() + (width / 2), (int) human.getY() + (height / 2));
        mHumanImage.draw(c);


        width = mZombieImage.getIntrinsicWidth();
        height = mZombieImage.getIntrinsicHeight();

        mZombieImage.setBounds((int) zombie.getX() - (width / 2), (int) zombie.getY() - (height / 2),
                (int) zombie.getX() + (width / 2), (int) zombie.getY() + (height / 2));
        mZombieImage.draw(c);

        c.restore();


    }

    public boolean doTouchEvent(MotionEvent e) {
        //do something
    }

}

//ZombieView variables
private ZombieThread thread;
private final SurfaceHolder surfaceHolder;
private Context context;

public ZombieView(Context context) {
    super(context);
    surfaceHolder = getHolder();
    surfaceHolder.addCallback(this);
    this.context = context;
    setFocusable(true); //makes sure we receive key-events
}

public ZombieView(Context context, AttributeSet attrs) {
    super(context, attrs);
    surfaceHolder = getHolder();
    surfaceHolder.addCallback(this);
    this.context = context;
    setFocusable(true); //makes sure we receive key-events
}

public ZombieView(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);
    surfaceHolder = getHolder();
    surfaceHolder.addCallback(this);
    this.context = context;
    setFocusable(true); //makes sure we receive key-events
}

public ZombieThread getThread() {
    return thread;
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
    thread = new ZombieThread(surfaceHolder, this, context);
    thread.setRunning(true);
    thread.start();
}
}

XML:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

<com.example.zombierun.zombierun.ZombieView android:background="#ccc"
    android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="20dp"
    android:paddingBottom="40dp"
    android:focusable="true"
    android:visibility="visible"
    android:id="@+id/customView" />

所以我现在的问题是: 当我启动应用程序时,我看到 Activity 和一个灰色区域,应该是 canvas / surfaceview。不幸的是,仅此而已。但是,当我通过按下主页按钮最小化应用程序时,我看到应用程序最小化时的 canvas(带有图像和背景颜色)。 logcat.

中没有显示错误

我假设 canvas 以某种方式停留在后台,或者不同视图之间存在重叠?这可能吗?

希望有人能帮我正确显示canvas。

提前致谢

在使用 SurfaceView 时不能使用 android:background="x"。您必须在 onDraw(Canvas c) 调用中手动绘制颜色,在本例中为 canvas.drawColor(Color.GREY) 。否则,您正在做的是让您设置的背景颜色绘制在表面视图的表面上,将其呈现为不透明的灰色。调用 onPause 时,视图被拆除,您可以暂时看到视图 window 覆盖层下方的表面,该表面绘制了 #ccc。

另外:为什么每帧让线程休眠 1/10 秒?你应该删除这一行。或者,如果您尝试以帧速率为目标:实现 1000 ms / 100 ms = 10 帧,也就是说,您正在以 10 fps 的速度绘制。