Android-рисование с использованием SurfaceView и Thread

Я пытаюсь нарисовать мяч на моем экране, используя 3 класса. Я немного прочитал об этом, и я нашел фрагмент кода, который работает с использованием 3 классов на одной странице, Игра с графикой в ​​Android

Я изменил код так, чтобы у меня был шар, который двигался и менял направление при ударе о стену, как на картинке ниже (это использует код в ссылке).

Скриншот движущегося мяча

Теперь я хотел бы разделить классы на 3 разные страницы, чтобы не делать все так тесно, все настроено одинаково.

Вот 3 класса, которые у меня есть.

  1. BallActivity.java
  2. Ball.java
  3. BallThread.java

package com.brick.breaker;
import android.app.Activity;
import android.os.Bundle;
import android.view.Window;
import android.view.WindowManager;


public class BallActivity extends Activity {

private Ball ball;

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    requestWindowFeature(Window.FEATURE_NO_TITLE);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);

    ball = new Ball(this);
    setContentView(ball);
}

@Override
protected void onPause() {

    super.onPause();

    setContentView(null);
    ball = null;

    finish();
}

}

package com.brick.breaker;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class Ball extends SurfaceView implements SurfaceHolder.Callback {

private BallThread ballThread = null;

private Bitmap bitmap;

private float x, y;
private float vx, vy;

public Ball(Context context) {
    super(context);

    bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ball);

    x = 50.0f;
    y = 50.0f;

    vx = 10.0f;
    vy = 10.0f;

    getHolder().addCallback(this);
    ballThread = new BallThread(getHolder(), this);
}

protected void onDraw(Canvas canvas) {

    update(canvas);

    canvas.drawBitmap(bitmap, x, y, null);
}

public void update(Canvas canvas) {

    checkCollisions(canvas);

    x += vx;
    y += vy;
}

public void checkCollisions(Canvas canvas) {

    if(x - vx < 0) {

        vx = Math.abs(vx);

    } else if(x + vx > canvas.getWidth() - getBitmapWidth()) {

        vx = -Math.abs(vx);
    }

    if(y - vy < 0) {

        vy = Math.abs(vy);

    } else if(y + vy > canvas.getHeight() - getBitmapHeight()) {

        vy = -Math.abs(vy);
    }
}

public int getBitmapWidth() {

    if(bitmap != null) {

        return bitmap.getWidth();

    } else {

        return 0;
    }
}

public int getBitmapHeight() {

    if(bitmap != null) {

        return bitmap.getHeight();

    } else {

        return 0;
    }
}

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

}

public void surfaceCreated(SurfaceHolder holder) {

    ballThread.setRunnable(true);
    ballThread.start();

}

public void surfaceDestroyed(SurfaceHolder holder) {

    boolean retry = true;
    ballThread.setRunnable(false);

    while(retry) {

        try {

            ballThread.join();
            retry = false;

        } catch(InterruptedException ie) {

            //Try again and again and again
        }

        break;
    }

    ballThread = null;

}

}

package com.brick.breaker;

import android.graphics.Canvas;
import android.view.SurfaceHolder;

public class BallThread extends Thread {

private SurfaceHolder sh;
private Ball ball;

private Canvas canvas;

private boolean run = false;

public BallThread(SurfaceHolder _holder,Ball _ball) {

    sh = _holder;
    ball = _ball;
}

public void setRunnable(boolean _run) {

    run = _run;
}

public void run() {

    while(run) {

        canvas = null;

        try {

            canvas = sh.lockCanvas(null);

            synchronized(sh) {

                ball.onDraw(canvas);
            }

        } finally {

            if(canvas != null) {

                sh.unlockCanvasAndPost(canvas);
            }

        }

    }
}

public Canvas getCanvas() {

    if(canvas != null) {

        return canvas;

    } else {

        return null;
    }
}
}

Вот картина, которая показывает результаты этих занятий.

Я пытался понять это, но, поскольку я довольно новичок в разработке для Android, я подумал, что могу попросить о помощи.

Кто-нибудь знает, из-за чего мяч тянет так? Код почти такой же, как в ссылке, и я попытался поэкспериментировать, чтобы найти решение, но не повезло.

5 ответов

Решение

Ну, как вы можете видеть на изображении, вы только нарисовали мяч. Вместо этого вам нужно перерисовывать черный фон (или все, что вы хотите) перед каждым рисованием мяча.

альтернативно, вы можете нарисовать черную область только в предыдущей позиции, но у вас могут возникнуть проблемы с ней позже, когда вы будете использовать больше объектов.

вот хороший пример, похожий на то, что вы делаете

Положи это

public void onDraw(Canvas canvas){
   canvas.drawColor(Color.BLACK);

.....

}

Беглый взгляд, и я должен сказать, что вы просто рисуете на одной поверхности и никогда не запрашиваете ваш вид поверхности для перерисовки. в конце блока finally в выражении IF используйте: postInvalidate(); Это должно заставить вид поверхности перерисовать себя.

Посмотрите, как я провел симуляцию маятника на http://som-itsolutions.blogspot.in/2012/06/android-graphics-and-animation-pendulum.html

Вы можете клонировать исходный код этого проекта с https://github.com/sommukhopadhyay/pendulumsimulation

[править] Ответ был неправильным, но комментарий был полезен, поэтому я оставлю этот ответ:

Не тот вопрос, который вы задали, но в вашем коде есть проблема. В Android вы можете писать только на экран в потоке пользовательского интерфейса. Это поток, который выполняет все обратные вызовы Activity и т. Д. Записывая данные на экран из BallThread, вы рискуете множеством странных сбоев в вашей программе.

Другие вопросы по тегам