使用mesh画线,并贴上纹理。画线类
public class MashLine extends Group {
private float mRadius = 0.0f;
private float mThickness = 0.0f;
private Array<Vector2> mPoints = null;
private Boolean bDrawOutlines = false;
private Boolean bDrawConstruction = false;
ShapeRenderer shapeRender = null;
ShaderProgram shader = null;
Mesh mesh = null;
FloatArray vertextArr = null;
Texture texture = null;
HashSet<TVertexData> vertexSet = null;
public MashLine() {
setSize(720,1280);
setTouchable(Touchable.disabled);
mRadius = 5.0f;
mPoints = new Array<Vector2>();
bDrawOutlines = true;
bDrawConstruction = true;
shapeRender = new ShapeRenderer();
shader = new ShaderProgram(Gdx.files.internal("surface_vertex.gles"), Gdx.files.internal("surface_fragment.gles"));
vertextArr = new FloatArray();
texture = new Texture("line.png");
texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear);
texture.setWrap(Texture.TextureWrap.Repeat, Texture.TextureWrap.Repeat);
mPoints = new Array<>();
mThickness = texture.getHeight() / 2;
vertexSet = new LinkedHashSet<>();
addListener(new ClickListener() {
Vector2 tmp = new Vector2();
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
tmp.setZero();
tmp.set(x, y);
mPoints.add(tmp.cpy());
return super.touchDown(event, x, y, pointer, button);
}
@Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
super.touchUp(event, x, y, pointer, button);
if (mPoints.size > 1){
Gdx.app.log("xx", "point size:" + mPoints.size);
if (mesh != null) {
mesh.dispose();
}
MeshTools meshtools = new MeshTools();
vertextArr = meshtools.convert(mPoints, texture, mThickness);
int num = vertextArr.size / 4;
mesh = new Mesh(
true,
num,
num,
new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),
new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_texCoord0")
);
mesh.setVertices(vertextArr.toArray());
ShortArray indexs = new ShortArray();
for (int i = 0; i < num; i++) {
indexs.add(i);
}
Gdx.app.log("", "" + indexs.size);
mesh.setIndices(indexs.toArray());
vertexSet.clear();
vertextArr.clear();
}
}
});
}
public void setClear(){
mPoints.clear();
}
public void setPoint(Vector2 vector2){
mPoints.add(vector2.cpy());
if (mPoints.size > 1) {
MeshTools meshtools = new MeshTools();
vertextArr = meshtools.convert(mPoints, texture, mThickness);
int num = vertextArr.size / 4;
mesh = new Mesh(
true,
num,
num,
new VertexAttribute(VertexAttributes.Usage.Position, 2, "a_position"),
new VertexAttribute(VertexAttributes.Usage.TextureCoordinates, 2, "a_texCoord0")
);
mesh.setVertices(vertextArr.toArray());
ShortArray indexs = new ShortArray();
for (int i = 0; i < num; i++) {
indexs.add(i);
}
Gdx.app.log("", "" + indexs.size);
mesh.setIndices(indexs.toArray());
vertexSet.clear();
vertextArr.clear();
}
}
@Override
public void act(float delta) {
super.act(delta);
for (int i = 0; i < mPoints.size; i++) {
Vector2 vec = mPoints.get(i);
shapeRender.setColor(Color.RED);
shapeRender.begin(ShapeRenderer.ShapeType.Filled);
shapeRender.circle(vec.x, vec.y, mRadius);
shapeRender.end();
}
for (int i = 0; i < mPoints.size; i++) {
int a = i-1<0 ? 0 : i - 1;
int b = i;
int c = i + 1 >= mPoints.size ? mPoints.size - 1 : i + 1;
int d = i + 2 >= mPoints.size ? mPoints.size - 1 : i + 2;
drawSegment(mPoints.get(a), mPoints.get(b), mPoints.get(c), mPoints.get(d));
}
}
@Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
if (mesh != null) {
Gdx.gl.glDepthMask(false);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
texture.bind();
shader.begin();
shader.setUniformMatrix("u_worldView", batch.getProjectionMatrix());
mesh.render(shader, GL20.GL_TRIANGLE_STRIP);
shader.end();
Gdx.gl.glDepthMask(true);
}
}
void insertData( TVertexData data, FloatArray array) {
Gdx.app.log("", data.toString());
array.add(data.pos.x);
array.add(data.pos.y);
array.add(data.u);
array.add(data.v);
}
void drawSegment(Vector2 p0, Vector2 p1,Vector2 p2 ,Vector2 p3 ) {
if (p1.equals(p2)) return;
Vector2 line = p2.cpy().sub(p1).nor();
Vector2 normal = new Vector2(-line.y, line.x).nor();
Vector2 tangent1 = (p0 == p1) ? line : ((p1.cpy().sub(p0).nor().add(line)).nor());
Vector2 tangent2 = (p2 == p3) ? line : ((p3.cpy().sub(p2).nor().add(line)).nor());
Vector2 miter1 = new Vector2(-tangent1.y, tangent1.x);
Vector2 miter2 = new Vector2(-tangent2.y, tangent2.x);
float length1 = mThickness / normal.dot(miter1);
float length2 = mThickness / normal.dot(miter2);
shapeRender.begin(ShapeRenderer.ShapeType.Line);
if (bDrawConstruction) {
Gdx.gl.glLineWidth(1.0f);
shapeRender.setColor(Color.BLACK);
shapeRender.line(p1, p2);
// draw normals in stippled red
shapeRender.setColor(Color.RED);
Gdx.gl.glEnable(GL20.GL_LINE_STRIP);
drawDashedLine(Color.RED, shapeRender, new Vector2(5f, 5f), p1.cpy().sub(normal.cpy().scl(mThickness)), p1.cpy().add(normal.cpy().scl(mThickness)), 0.5f);
drawDashedLine(Color.RED, shapeRender, new Vector2(5f, 5f), p2.cpy().sub(normal.cpy().scl(mThickness)), p2.cpy().add(normal.cpy().scl(mThickness)), 0.5f);
Gdx.gl.glDisable(GL20.GL_LINE_STRIP);
shapeRender.setColor(Color.GRAY);
Gdx.gl.glEnable(GL20.GL_LINE_STRIP);
shapeRender.line(p1.cpy().sub(normal.cpy().scl(mThickness)), p2.cpy().sub(normal.cpy().scl(mThickness)));
shapeRender.line(p1.cpy().add(normal.cpy().scl(mThickness)), p2.cpy().add(normal.cpy().scl(mThickness)));
Gdx.gl.glDisable(GL20.GL_LINE_STRIP);
}
if (bDrawOutlines) {
Gdx.gl.glLineWidth(1.5f);
shapeRender.setColor(Color.BLACK);
Vector2 v0 = p1.cpy().sub(miter1.cpy().scl(length1));
Vector2 v1 = p2.cpy().sub(miter2.cpy().scl(length2));
Vector2 v2 = p1.cpy().add(miter1.cpy().scl(length1));
Vector2 v3 = p2.cpy().add(miter2.cpy().scl(length2));
shapeRender.line(v0, v1);
shapeRender.line(v2, v3);
Gdx.gl.glEnable(GL20.GL_LINE_STRIP);
drawDashedLine(Color.BLACK, shapeRender,new Vector2(5f, 5f), p1.cpy().sub(miter1.cpy().scl(length1)), p1.cpy().add(miter1.cpy().scl(length1)), 0.5f);
drawDashedLine(Color.BLACK, shapeRender, new Vector2(5f, 5f), p1.cpy().sub(miter1.cpy().scl(length1)), p2.cpy().add(miter2.cpy().scl(length2)), 0.5f);
drawDashedLine(Color.BLACK, shapeRender,new Vector2(5f, 5f), p2.cpy().sub(miter2.cpy().scl(length2)), p2.cpy().add(miter2.cpy().scl(length2)), 0.5f);
Gdx.gl.glDisable(GL20.GL_LINE_STRIP);
}
shapeRender.end();
}
void drawDashedLine(Color color ,ShapeRenderer renderer,Vector2 dashes ,Vector2 start,Vector2 end ,Float width) {
if (dashes.x == 0.0f) {
return;
}
float dirX = end.x - start.x;
float dirY = end.y - start.y;
float length = Vector2.len(dirX, dirY);
dirX /= length;
dirY /= length;
float curLen = 0f;
float curX = 0f;
float curY = 0f;
renderer.setColor(color);
while (curLen <= length) {
curX = start.x + dirX * curLen;
curY = start.y + dirY * curLen;
renderer.rectLine(curX, curY, curX + dirX * dashes.x, curY + dirY * dashes.x, width);
curLen += dashes.x + dashes.y;
}
}
private Vector2 save4() {
this.x = ((Math.round(this.x * 10000f)) / 10000f);
this.y = ((Math.round(this.y * 10000f)) / 10000f);
return null;
}
}
控制顶点
package wk.demo.block.screen.load;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.math.Interpolation;
import com.badlogic.gdx.math.Vector2;
import com.badlogic.gdx.scenes.scene2d.Group;
import com.badlogic.gdx.scenes.scene2d.InputEvent;
import com.badlogic.gdx.scenes.scene2d.actions.Actions;
import com.badlogic.gdx.scenes.scene2d.ui.Image;
import com.badlogic.gdx.scenes.scene2d.utils.ClickListener;
import com.badlogic.gdx.utils.Align;
import com.badlogic.gdx.utils.Array;
import com.tony.rider.test.MashLine;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import wk.demo.block.Bse;
import wk.demo.block.BseInterpolation;
import wk.demo.block.constant.Constant;
import wk.demo.block.utils.ShapeDraw;
public class GameView extends Group {
private ShapeDraw shapeDraw;
MashLine line ;
public GameView(){
setDebug(true);
setSize(Constant.width,720);
xx();
line = new MashLine();
addActor(line);
this.addListener(new ClickListener(){
@Override
public void clicked(InputEvent event, float x, float y) {
if (y>720)return;
super.clicked(event, x, y);
long l = System.currentTimeMillis() - lastTime;
lastTime = System.currentTimeMillis();
if (l<1000){
Image image = new Image(new Texture("white_cir.png"));
addActor(image);
image.setPosition(x,y);
image.addListener(imgaeListener);
array.add(image);
array1.clear();
controlPoint.clear();
for (int i = 0; i < array.size; i++) {
controlPoint.add(array.get(i).getPosition());
}
jisuan(controlPoint);
}
}
});
Image image = new Image(new Texture("white_squ.png"));
image.setPosition(getWidth() - 260,830);
addActor(image);
Image image1 = new Image(new Texture("white_squ.png"));
addActor(image1);
image1.setY(830);
Image image3 = new Image(new Texture("white_squ.png"));
addActor(image3);
image3.setY(830);
image3.setX(0,Align.center);
image3.addListener(new ClickListener(){
@Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
image1.setScale(1,1);
}
});
image.addListener(new ClickListener(){
@Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
// image1.addAction(Actions.scaleTo(3,3,3, new Bse(array1)));
BseInterpolation bseInterpolation = new BseInterpolation();
bseInterpolation.setCurve(0.25F, 0, 0.75F, 1F);
image1.addAction(Actions.scaleTo(3,3,3, bseInterpolation));
save();
}
});
}
Image image;
private boolean start = false;
private long lastTime = Integer.MIN_VALUE;
private ClickListener imgaeListener = new ClickListener(){
@Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
return super.touchDown(event, x, y, pointer, button);
}
@Override
public void touchDragged(InputEvent event, float x, float y, int pointer) {
super.touchDragged(event, x, y, pointer);
event.getTarget().setPosition(event.getStageX(),event.getStageY());
array1.clear();
controlPoint.clear();
for (int i = 0; i < array.size; i++) {
controlPoint.add(array.get(i).getPosition());
}
jisuan(controlPoint);
line.setClear();
for (int i = 0; i < array1.size; i++) {
Vector2 vector2 = array1.get(i);
line.setPoint(vector2);
}}
@Override
public void clicked(InputEvent event, float x, float y) {
super.clicked(event, x, y);
}
};
private Array<Vector2> controlPoint = new Array<Vector2>();
private Array<Image> array = new Array<>();
private Array<Vector2> array1 = new Array<>();
Vector2 sss = new Vector2(360,0);
public void xx() {
// [{x:69,y:732},{x:366,y:111},{x:300,y:774},{x:681,y:684}]
// controlPoint.add(new Vector2(69, 732)); //起点
// controlPoint.add(new Vector2(366, 111)); //控制点
// controlPoint.add(new Vector2(300, 774)); //控制点
// controlPoint.add(new Vector2(681, 684)); //终点
controlPoint.add(new Vector2(0, 0)); //起点
controlPoint.add(sss);
controlPoint.add(new Vector2(710, 0)); //终点
for (Vector2 vector2 : controlPoint) {
Image image = new Image(new Texture("white_cir.png"));
addActor(image);
image.setPosition(vector2.x,vector2.y);
image.addListener(imgaeListener);
array.add(image);
}
jisuan(controlPoint);
shapeDraw = new ShapeDraw();
addActor(shapeDraw);
shapeDraw.setArray(array1);
shapeDraw.setLine(controlPoint);
}
public void jisuan(Array<Vector2> controlPoint){
int n = controlPoint.size - 1; //
int i, r;
float u;
// u的步长决定了曲线点的精度
for (u = 0; u <= 1; u += 0.01) {
Vector2 p[] = new Vector2[n + 1];
for (i = 0; i <= n; i++) {
p[i] = new Vector2(controlPoint.get(i));
}
for (r = 1; r <= n; r++) {
for (i = 0; i <= n - r; i++) {
p[i].x = (1 - u) * p[i].x + u * p[i + 1].x;
p[i].y = (1 - u) * p[i].y + u * p[i + 1].y;
}
}
array1.add(p[0]);
}
}
public void save(){
try {
FileWriter stream = new FileWriter(new File("./text.txt"));
for (Vector2 vector2 : controlPoint) {
stream.write(vector2.x+", "+vector2.y+" ");
}
stream.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private float timess = 0;
private int index= 0;
private int deIndex = 1;
@Override
public void act(float delta) {
super.act(delta);
timess += delta;
if (start) {
if (timess > 0.1F){
sss.y = sss.y +5;
array1.clear();
jisuan(controlPoint);
if (index>=array1.size-1)deIndex =-1;
if (index<=0)deIndex = 1;
Vector2 vector2 = array1.get(index);
image.setPosition(vector2.x,vector2.y,Align.center);
timess = 0;
index+=deIndex;
}
}
}
}
效果:

网友评论