web-dev-qa-db-fra.com

Dessin Android avec SurfaceView et Thread

J'essaie de dessiner une balle sur mon écran en utilisant 3 classes. J'ai lu un peu à ce sujet et j'ai trouvé un extrait de code qui fonctionne avec les 3 classes d'une page, Jouer avec des graphiques dans Android

J'ai modifié le code pour avoir une balle en mouvement qui change de direction lorsque je frappe le mur, comme dans l'image ci-dessous (le code est utilisé dans le lien) .

moving ball screenshot

Maintenant, j'aime séparer les classes en 3 pages différentes pour ne pas rendre tout ce monde encombré, tout est configuré de la même manière.

Voici les 3 classes que j'ai.

  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;
    }
}
}

Voici une image qui montre le résultat de ces classes.

enter image description here

J'ai essayé de comprendre cela, mais depuis que je suis assez nouveau dans le développement Android, je pensais pouvoir demander de l'aide.

Est-ce que quelqu'un sait ce qui fait que la balle est tirée comme ça? Le code est à peu près le même que celui dans le lien et j'ai essayé d'expérimenter pour trouver une solution mais pas de chance.

10
Morten Høgseth

comme vous pouvez le voir sur l’image, vous n’avez fait que tirer la balle. au lieu de cela, vous devez redessiner un fond noir (ou celui que vous souhaitiez) avant chaque fois que vous tirez le ballon.

alternativement, vous pouvez dessiner une zone noire uniquement sur la position précédente, mais vous pourriez avoir des problèmes avec celle-ci ultérieurement, lorsque vous utilisez plus d'objets.

voici un bel échantillon , semblable à ce que vous faites

15

Un rapide coup d'œil et je dois dire que vous dessinez simplement sur la même surface et que vous ne demandez jamais à votre surface de se redessiner. à la fin du bloc finally, dans l'instruction IF, utilisez: postInvalidate(); Cela devrait entraîner le redessin de la vue de surface.

1
Sorceri

mettre ceci

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

.....

}
1
wdog

Voyez comment j'ai fait la simulation du pendule à http://som-itsolutions.blogspot.in/2012/06/Android-graphics-and-animation-pendulum.html

Vous pouvez copier le code source de ce projet depuis https://github.com/sommukhopadhyay/pendulumsimulation

0