2012-06-08 16 views
9

Estoy tratando de dibujar una bola en mi pantalla usando 3 clases. He leído un poco sobre esto y encontré un fragmento de código que funciona usando las 3 clases en una página, Playing with graphics in AndroidDraw de Android usando SurfaceView y Thread

He alterado el código para que tenga una bola que se mueve y cambia de dirección al golpear la pared como el imagen debajo de (esto está usando el código en el enlace).

moving ball screenshot

Ahora me gusta separar las clases en 3 páginas diferentes para no hacer todo tan lleno de gente, todo está configurado de la misma manera.

Aquí están las 3 clases que tengo.

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

Aquí es una imagen que muestra el resultado de estas clases.

enter image description here

He tratado de resolver esto, pero ya que soy bastante nuevo en el desarrollo de Android pensé que podía pedir ayuda.

¿Alguien sabe qué está causando que la bola se dibuje así? El código es prácticamente el mismo que el del enlace y he intentado experimentar para encontrar una solución, pero no tuve suerte.

Respuesta

14

bueno, como puedes ver en la imagen, solo dibujaste el balón. en su lugar, debe volver a dibujar un fondo negro (o lo que sea que desee) antes de cada vez que dibuja la pelota.

alternativamente, puede dibujar un área negra solo en la posición anterior, pero puede tener problemas con ella más tarde, cuando use más objetos.

here's a nice sample, similar a lo que se hace

+0

Yepp que fija mi problema, en el método onDraw he añadido el lienzo línea. drawColor (Color.BLACK); antes de dibujar el balón para que la pantalla se llenara de negro, eliminando las películas no deseadas de bola verde. Thx mucho =) –

+0

Por cierto, para una animación mucho más suave y más rápida, recomendaría usar OpenGL. el lienzo es solo para cosas simples, especialmente por ahora que la mayoría de los dispositivos todavía no tienen GPU ayudando con las cosas gráficas, ya que la mayoría todavía están en la versión Android "vieja" (pan de jengibre). –

+0

excelente consejo =) Voy a perder el tiempo con el código anterior y luego crear un nuevo proyecto y hacer la misma lógica pero usando OpenGL. Thx para el consejo :) –

1

Una mirada rápida y tendría que decir que está dibujando en la misma superficie y nunca solicita que su vista superficial se vuelva a dibujar. al final del bloque finally, en el uso de IF Statement: postInvalidate(); Eso debería causar que la vista de superficie se redibuje.

1

poner este

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

..... 

} 
-1

[editar] La respuesta fue incorrecta, pero el comentario es útil por lo que voy a dejar esta respuesta por:

No es la pregunta que hizo, pero hay un problema en su código. En Android, solo se le permite escribir en la pantalla en el hilo de la interfaz de usuario. Este es el hilo que ejecuta todas las devoluciones de llamadas de actividad, etc. Al escribir en la pantalla de BallThread, se arriesga a muchas fallas extrañas en su programa.

+2

'SurfaceView' se puede actualizar desde otro hilo - http://developer.android.com/reference/android/view/SurfaceView.html –

+0

Gracias. Aprendí algo nuevo. –

Cuestiones relacionadas