创建一个像风景精灵一样的随机正弦图 [英] Create a random, sine graph like landscape sprite

查看:33
本文介绍了创建一个像风景精灵一样的随机正弦图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有这个精灵:

我在运行时创建了一个随机景观:

And I created a random landscape during runtime:

然后,我想用精灵平铺线下方的区域:

And then, I want to tile the area below the line with the sprite:

这是游戏场地,因此它也应该是一个物理对象(在 Box2D 中).

在这里,他给出了如何将其变成物理体的示例.那么,我如何在代码中做图形部分?

Here, he given a sample of how to make this a physics body. So, how do I do the graphics part in code?

查看 AndEngine 示例,文件 RepeatingSpriteBackgroundExample.java,这不是我所需要的,但我应该坚持这个想法并改变 RepeatingSpriteBackground 类 满足我的需要?但是,我认为这不是最好的方法......

Looking in the AndEngine examples, file RepeatingSpriteBackgroundExample.java, it's not exactly what I need but should I stick to this idea and change the RepeatingSpriteBackground class for my needs? I don't think that would be the best method however...

提前致谢.

推荐答案

我对 Box2D 或 AndEngine 不太了解,但我认为这是一个有趣的问题,并制作了一个可以绘制随机地形"的自定义 SurfaceView,例如你照片中的那个.(希望它对您或其他人有用,至少我学到了一些新东西:p)

单色地形:平铺背景地形:平铺位图:

I don't really know about Box2D or AndEngine, but I thought this was an interesting problem and made a custom SurfaceView that can draw a random "terrain" like the one in your picture. (Hopefully it will be of use to you or someone else, at least I learnt some new stuff :p)

Single colour terrain: Tiled background-terrain: The tiled bitmap:

我的代码如下:

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

如果这对您有帮助,您可能需要调整参数以获得适合您需要的形状,并且最有可能添加点之间最小距离的参数等.稍微优化一下背景的绘制也是一个好主意,比如从底部向上绘制到地形的最大高度,以尽量减少对不可见区域的绘制.我也应该可以减少对 getHeight() 和 getWidth() 的调用次数.

If this is of any help to you you'll probably have to play around with the parameters to get shapes that suits your needs and most likely add a parameter for minimum distance between points etc. It is also a good idea to optimize the drawing of the background a bit, like drawing from the bottom up to the maximum height of the terrain, to minimize drawing to invisible areas. I should also be possible to reduce the amount of calls to getHeight() and getWidth().

干杯!

这篇关于创建一个像风景精灵一样的随机正弦图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆