2011-11-28 5 views
5

Digamos que tengo este elemento sprite:crear un gráfico de azar, sine como sprites paisaje

Sample sprite

Y he creado un paisaje al azar durante el tiempo de ejecución:

Dynamic runtime landscape

Y entonces, desea baldosar el área debajo de la línea con el sprite:

enter image description here

Este es el terreno del juego, por lo tanto, también debe ser un objeto de física (En Box2D).

Here, dio una muestra de cómo hacer de este un cuerpo de física. Entonces, ¿cómo hago la parte de gráficos en el código?

EDIT: Buscando en los ejemplos andengine, presentar RepeatingSpriteBackgroundExample.java, no es exactamente lo que necesito, pero debería adherirse a esta idea y cambiar el RepeatingSpriteBackground class para mis necesidades? No obstante, no creo que sea el mejor método ...

Gracias de antemano.

Respuesta

6

No sé realmente acerca de Box2D o AndEngine, pero pensé que era un problema interesante e hice una SurfaceView personalizada que puede dibujar un "terreno" aleatorio como el de la imagen. (Espero que sea de utilidad para usted o alguien más, al menos he aprendido algunas cosas nuevas: p)

solo color terreno: screenshot Mosaico de fondo terreno: screenshot El mapa de bits de azulejos:
resource bitmap

Mi código es el siguiente:

public class PathView extends SurfaceView implements SurfaceHolder.Callback{ 
private class DrawingRunnable implements Runnable{ 
    private final static int minPointsOnScreen = 3; 
    SurfaceHolder surfaceHolder; 
    Random rand = new Random(); 

    private Path path; 
    private Paint pathPaint; 
    Bitmap background; 
    private Paint tilePaint;   

    volatile boolean running = false; 

    int width; 
    int height; 
    int maxHeight; 

    protected DrawingRunnable(SurfaceHolder sh){ 
     surfaceHolder = sh; 

     pathPaint = new Paint(); 
     pathPaint.setColor(0xFF000000); 
     pathPaint.setStrokeWidth(4); 

     tilePaint = new Paint(); 
    } 

    protected void createPath(){ 
     path = new Path(); 
     path.setFillType(Path.FillType.WINDING); 

     path.setLastPoint(0, height); 
     int lastX = 0, lastY = height - rand.nextInt(maxHeight); 
     path.lineTo(lastX,lastY); 

     int newX=lastX, newY=lastY; 

     do{ 
      lastX = newX; lastY = newY; 
      newX += rand.nextInt(width/minPointsOnScreen); 
      newY = height - rand.nextInt(maxHeight); 
      path.cubicTo(
        interpolateLinear(lastX, newX, 0.333f), 
        lastY, 
        interpolateLinear(lastX, newX, 0.666f), 
        newY, 
        newX, newY); 
     }while(newX <= width); 

     path.lineTo(width, height); 
    } 

    private int interpolateLinear(int start, int end, float part){ 
     return (int) (start*(1-part) + end*part); 
    } 

    @Override 
    public void run(){ 
     while(running){ 
      Canvas c = null; 
      try{ 
       c = surfaceHolder.lockCanvas(null); 
       synchronized (surfaceHolder) { 
        doDraw(c); 
       } 
      } finally{ if(c!=null) surfaceHolder.unlockCanvasAndPost(c); } 
      SystemClock.sleep(40); 
     } 
    } 

    private void doDraw(Canvas c){ 
     c.drawColor(0xFFFFFFFF); 
     //c.drawPath(path, pathPaint); //Use this to draw a single-colour. (First screenshot) 
     c.clipPath(path); 
     for(int y = 0; y+background.getHeight() < height+background.getHeight(); y+=background.getHeight()){ 
      for(int x = 0; x+background.getWidth() < width+background.getWidth(); x+=background.getWidth()){ 
       c.drawBitmap(background, x, y, tilePaint); 
      } 
     } 
    } 
} 

private ExecutorService exec; 
private SurfaceHolder holder; 
private DrawingRunnable drawer; 

public PathView(Context c){ super(c); init(c); } 
public PathView(Context c, AttributeSet as){ super(c, as); init(c); } 
public PathView(Context c, AttributeSet as, int defStyle){ super(c, as, defStyle); init(c); } 

private void init(Context c){ 
    exec = Executors.newSingleThreadExecutor(); 
    holder = getHolder(); 
    holder.addCallback(this); 
} 

public void surfaceCreated(SurfaceHolder sh){ 
    if(drawer == null){ 
     drawer = new DrawingRunnable(holder); 
     drawer.width = getWidth(); 
     drawer.height = getHeight(); 
     drawer.maxHeight = drawer.height/2; 
     drawer.createPath(); 
     drawer.background = BitmapFactory.decodeResource(getResources(), R.drawable.tile); 
    } 
    drawer.running = true; 
    exec.execute(drawer); 
} 
public void surfaceDestroyed(SurfaceHolder sh){ 
    drawer.running = false; 
} 
public void surfaceChanged(SurfaceHolder sh, int format, int width, int height){} 
} 

Si esto es de ninguna ayuda a que usted probablemente tendrá que jugar un poco con los parámetros para obtener las formas que se adapte sus necesidades y lo más probable es que agregue un parámetro para la distancia mínima entre puntos, etc. También es una buena idea optimizar un poco el dibujo del fondo, como dibujar de abajo hacia arriba a la altura máxima del terreno, para minimizar el dibujo a áreas invisibles También debería ser posible reducir la cantidad de llamadas a getHeight() y getWidth().

¡Salud!

+0

Gracias, pero no es exactamente lo que necesitaba. Antes que nada, And Engine usa su propia versión de SurfaceView (aunque creo que también podría subclasificarla). Pero necesito descubrir cómo marco el paisaje con una textura cuadrada, los algoritmos para crear rutas son la parte más fácil :( – Jong

+0

Cambié el doDraw() un poco para hacer esto en caso de que sea de alguna ayuda para usted:) – Jave

+0

Funciona muy bien, pero no puedo usar estas clases nativas de Android cuando desarrollo con AndEngine. Necesito usar las clases de AndEngine. Sin embargo, echaré un vistazo si puedo combinarlos ... (SurfaceView y SurfaceView de AndEngine) – Jong