美文网首页libgdx专题libgdx游戏开发
libgdx利用mesh生成2d游戏自定义地形

libgdx利用mesh生成2d游戏自定义地形

作者: 纯洁的坏蛋 | 来源:发表于2016-08-22 14:13 被阅读409次

    首先来看看效果:


    原理:分为两部分,上面的是线条,下面是多边形, 所以需要两个Mesh(点的数据就是随便模拟了几个)

    1.地下部分

    地下部分

    原理:根据顶点数据+底部的点组成一些列的点 这些点放入Mesh画出来。

    points.add(new Vector2(114, 240));
    //points.add(new Vector2(800, 240));
    points.add(new Vector2(268, 434));
    points.add(new Vector2(400, 450));
    points.add(new Vector2(626, 257));
    points.add(new Vector2(921, 244));
    
    linepoints.addAll(points);
    stage.addActor(new GroundActor(points));
    

    下面来GroundActor的写法

    1.定义shader

    ShaderProgram shader;
    
    shader = new ShaderProgram(Gdx.files.internal("surface_vertex.gles"), Gdx.files.internal     ("surface_fragment.gles"));
    

    surface_vertex.gles

    attribute vec4 a_position;
    attribute vec4 a_color;
    attribute vec2 a_texCoord0;
    uniform mat4 u_worldView;
    
    varying vec4 v_color;
    varying vec2 v_texCoords;
    void main()
    {
     v_color = vec4(1, 1, 1, 1);
     gl_Position =  u_worldView * a_position;
     v_texCoords = a_texCoord0;
    }
    

    surface_fragment.gles

    #ifdef GL_ES    
            precision mediump float;
    #endif
    varying vec2 v_texCoords;
    uniform sampler2D u_texture;
    varying vec4 v_color;
    
    void main(){    
            gl_FragColor = v_color * texture2D(u_texture, v_texCoords);
    }
    

    2.定义mesh

    Mesh mesh;
    mesh = new Mesh(true, points.size * 2, points.size * 2,        
    new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),        
    new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_texCoord0"));
    

    3.定义Texture

    private final Texture texture;
    texture = new Texture("tile.png");
    texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
    texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
    

    4.解析顶点数据

    //每个顶点需要占4个位置, 点坐标2个,纹理坐标2个,根据上面的顶点生成一个相应的底部顶点
    //总共需要points.size * 2个顶点, 每个顶点占4个位置
    float vertexs[] = new float[2 * 2 * 2 * points.size];
    
    int offset = 0;
    for (Vector2 point : points){    
    //下面的顶点 比如顶点2
     vertexs[offset + 0] = point.x;  //横坐标
     vertexs[offset + 1] = 0;    //纵坐标,顶部的点Y都是0
     vertexs[offset + 2] = point.x / texture.getWidth();    //纹理坐标,横轴
     vertexs[offset + 3] = 0;    //纹理坐标
    
    //上面的顶点 比如1 
     vertexs[offset + 4] = point.x;    
     vertexs[offset + 5] = point.y;    
     vertexs[offset + 6] = point.x / texture.getWidth();    
     vertexs[offset + 7] = point.y / texture.getHeight();    
    
    offset += 8;
    }
    
    //设置顶点数据到mesh中
    mesh.setVertices(vertexs);
    short[] indices1 = new short[points.size * 2];
    for (int i = 0; i < indices1.length; i++){   
      indices1[i] = (short) i;
    }
    //设置索引,就是依顺序0,1,2,3,4,5,6,7,8,9...
    mesh.setIndices(indices1);
    

    5.把Mesh画出来

    Gdx.gl.glEnable(GL20.GL_BLEND);
    Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    
    //把stage的相机绑定在mesh上
    shader.begin();shader.setUniformMatrix("u_worldView", getStage().getCamera().combined);texture.bind(0);
    mesh.render(shader, GL20.GL_TRIANGLE_STRIP);
    shader.end();
    
    Gdx.gl.glDisable(GL20.GL_BLEND);
    

    至此底部的地形就画出来了,剩下的就是上面部分

    Paste_Image.png

    这部分原理差不多,只是生成点的方式不一样而已

    Paste_Image.png

    只需要生成顶点的时候上移和下移一下就好了。

    int offset = 0;
    Vector2 pt = new Vector2();
    for (int i = 0; i < points.size; ++i){    
      pt.set(points.get(i).cpy());    
      vertexs[offset + 0] = pt.x;    
      vertexs[offset + 1] = pt.y - texture.getHeight() / 2f;    //下移一段距离
      vertexs[offset + 2] = pt.x / texture.getWidth();   
      vertexs[offset + 3] = 1;    
      vertexs[offset + 4] = pt.x;    
      vertexs[offset + 5] = pt.y + texture.getHeight() / 2f;    //上移一段距离 其他的都一样
      vertexs[offset + 6] = pt.x / texture.getWidth();    
      vertexs[offset + 7] = 0;    
    
      offset += 8;
    }
    

    如果有不懂的,可以和我一起交流,直接留言或者加入QQ群:
    QQ群:187378034

    完整代码(groundActor):

    public class GroundActor extends Actor{
    
        ShaderProgram shader;
        Mesh mesh;
        Array<Vector2> points;
        private final Texture texture;
    
        public GroundActor(Array<Vector2> points){
            this.points = points;
    
            texture = new Texture("tile.png");
            texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
            texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
    
            float vertexs[] = new float[2 * 2 * 2 * points.size];
    
            int offset = 0;
            for (Vector2 point : points){
                vertexs[offset + 0] = point.x;
                vertexs[offset + 1] = 0;
                vertexs[offset + 2] = point.x / texture.getWidth();
                vertexs[offset + 3] = 0;
    
                vertexs[offset + 4] = point.x;
                vertexs[offset + 5] = point.y;
                vertexs[offset + 6] = point.x / texture.getWidth();
                vertexs[offset + 7] = point.y / texture.getHeight();
    
                offset += 8;
            }
    
            shader = new ShaderProgram(Gdx.files.internal("surface_vertex.gles"), Gdx.files.internal
                    ("surface_fragment.gles"));
    
            mesh = new Mesh(true, points.size * 2, points.size * 2,
                    new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),
                    new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_texCoord0"));
    
            mesh.setVertices(vertexs);
    
            short[] indices1 = new short[points.size * 2];
    
            for (int i = 0; i < indices1.length; i++){
                indices1[i] = (short) i;
            }
    
            mesh.setIndices(indices1);
        }
    
        @Override
        public void draw(Batch batch, float parentAlpha) {
            super.draw(batch, parentAlpha);
            Gdx.gl.glEnable(GL20.GL_BLEND);
            Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    
            shader.begin();
            shader.setUniformMatrix("u_worldView", getStage().getCamera().combined);
            texture.bind(0);
            mesh.render(shader, GL20.GL_TRIANGLE_STRIP);
            shader.end();
    
            Gdx.gl.glDisable(GL20.GL_BLEND);
        }
    }
    

    完整的代码(LineActor)

    public class LineActor extends Actor{
        ShaderProgram shader;
        Mesh mesh;
        Array<Vector2> points;
        private Texture texture;
    
        public LineActor(Array<Vector2> points){
            this.points = points;
    
            texture = new Texture("line.png");
            texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
            texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
    
            float vertexs[] = new float[2 * 2 * 2 * points.size];
    
            int offset = 0;
            Vector2 pt = new Vector2();
            for (int i = 0; i < points.size; ++i){
                pt.set(points.get(i).cpy());
    
                vertexs[offset + 0] = pt.x;
                vertexs[offset + 1] = pt.y - texture.getHeight() / 2f;
                vertexs[offset + 2] = pt.x / texture.getWidth();
                vertexs[offset + 3] = 1;
    
                vertexs[offset + 4] = pt.x;
                vertexs[offset + 5] = pt.y + texture.getHeight() / 2f;
                vertexs[offset + 6] = pt.x / texture.getWidth();
                vertexs[offset + 7] = 0;
    
                offset += 8;
            }
    
            shader = new ShaderProgram(Gdx.files.internal("surface_vertex.gles"), Gdx.files.internal
                    ("surface_fragment.gles"));
    
            mesh = new Mesh(true, points.size * 2, points.size * 2,
                    new VertexAttribute(VertexAttributes.Usage.Position, 2, ShaderProgram.POSITION_ATTRIBUTE),
                    new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, ShaderProgram
                            .TEXCOORD_ATTRIBUTE + "0"));
    
            mesh.setVertices(vertexs);
    
            short[] indices1 = new short[points.size * 2];
    
            for (int i = 0; i < indices1.length; i++){
                indices1[i] = (short) i;
            }
    
            mesh.setIndices(indices1);
        }
    
        @Override
        public void draw(Batch batch, float parentAlpha) {
            super.draw(batch, parentAlpha);
    
            Gdx.gl.glEnable(GL20.GL_BLEND);
            Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
    
            texture.bind();
            shader.begin();
            shader.setUniformMatrix("u_worldView", getStage().getCamera().combined);
            mesh.render(shader, GL20.GL_TRIANGLE_STRIP);
            shader.end();
    
            Gdx.gl.glDisable(GL20.GL_BLEND);
        }
    }
    

    相关文章

      网友评论

      本文标题:libgdx利用mesh生成2d游戏自定义地形

      本文链接:https://www.haomeiwen.com/subject/fsxgsttx.html