2011-11-28 15 views
5

phép nói rằng tôi có sprite này:Tạo một ngẫu nhiên, đồ thị hình sin như cảnh quan sprite

Sample sprite

Và tôi đã tạo ra một cảnh quan ngẫu nhiên trong thời gian chạy:

Dynamic runtime landscape

Và sau đó, tôi muốn lát khu vực bên dưới đường kẻ đó bằng chữ:

enter image description here

Đây là mặt đất trò chơi, do đó nó cũng phải là một đối tượng vật lý (Trong Box2D).

Here, ông đã đưa ra một ví dụ về cách tạo cơ sở vật lý này. Vì vậy, làm thế nào để làm một phần đồ họa trong mã?

EDIT: Nhìn trong các ví dụ AndEngine, nộp RepeatingSpriteBackgroundExample.java, nó không phải là chính xác những gì tôi cần, nhưng tôi nên dính vào ý tưởng này và thay đổi RepeatingSpriteBackground class cho nhu cầu của tôi? Tuy nhiên, tôi không nghĩ đó sẽ là phương pháp tốt nhất ...

Xin cảm ơn trước.

Trả lời

6

Tôi không thực sự biết về Box2D hoặc AndEngine, nhưng tôi nghĩ đây là một vấn đề thú vị và tạo SurfaceView tùy chỉnh có thể vẽ một "địa hình" ngẫu nhiên như hình ảnh trong bức ảnh của bạn. (Hy vọng rằng nó sẽ được sử dụng cho bạn hoặc người khác, ít nhất tôi học được một số công cụ mới: p)

Đơn sắc địa hình: screenshot lát gạch nền địa hình: screenshot Các bitmap lát gạch:
resource bitmap

mã của tôi là như sau:

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){} 
} 

Nếu đây là của bất kỳ trợ giúp cho bạn có thể bạn sẽ phải chơi xung quanh với các thông số để có được hình dạng phù hợp nhu cầu của bạn và rất có thể thêm thông số cho khoảng cách tối thiểu giữa các điểm, vv .. Bạn cũng nên tối ưu hóa bản vẽ nền một chút, như vẽ từ dưới lên đến chiều cao tối đa của địa hình, để thu nhỏ bản vẽ khu vực vô hình. Tôi cũng có thể giảm số lượng cuộc gọi đến getHeight() và getWidth().

Chúc mừng!

+0

Xin cảm ơn, nhưng nó không chính xác những gì tôi cần. Trước hết, AndEngine sử dụng phiên bản SurfaceView của riêng mình (mặc dù tôi đoán tôi cũng có thể phân lớp nó). Nhưng tôi cần phải tìm hiểu làm thế nào để gạch hình phong cảnh với một kết cấu hình vuông, các thuật toán để tạo đường dẫn là phần dễ dàng hơn: ( – Jong

+0

Tôi đã thay đổi doDraw() một chút để làm điều này trong trường hợp nó giúp bạn:) – Jave

+0

Nó hoạt động tuyệt vời, nhưng tôi không thể sử dụng các lớp học android bản địa này khi phát triển với AndEngine - tôi cần sử dụng các lớp AndEngine. Tuy nhiên, tôi sẽ có một cái nhìn nếu tôi có thể kết hợp cả hai ... (SurfaceView của bạn và AndEngine's SurfaceView) – Jong