Created
November 26, 2014 03:25
-
-
Save hiepnd/5b36227fe45b74aa1108 to your computer and use it in GitHub Desktop.
Amazing Wire's tail, rewritten in libgdx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.badlogicgames.plane; | |
import java.nio.ByteBuffer; | |
import java.nio.ByteOrder; | |
import java.nio.FloatBuffer; | |
import com.badlogic.gdx.Gdx; | |
import com.badlogic.gdx.graphics.Camera; | |
import com.badlogic.gdx.graphics.Color; | |
import com.badlogic.gdx.graphics.GL20; | |
import com.badlogic.gdx.graphics.glutils.ImmediateModeRenderer20; | |
import com.badlogic.gdx.graphics.glutils.ShaderProgram; | |
import com.badlogic.gdx.math.Vector2; | |
public class Tail { | |
private static final int MaxTailBufferCapacity = 100; | |
private static final int TailVertexSize = 2; | |
private static final float SnakeLineWidth = 20; | |
private Color color; | |
private int bufferCount; | |
private Vector2 points[]; | |
private FloatBuffer buffer; | |
private ShaderProgram shader; | |
public Tail() { | |
bufferCount = 0; | |
color = Color.RED; | |
ByteBuffer buf = ByteBuffer.allocateDirect(MaxTailBufferCapacity*2*TailVertexSize*4); | |
buf.order(ByteOrder.nativeOrder()); | |
buffer = buf.asFloatBuffer(); | |
points = new Vector2[MaxTailBufferCapacity]; | |
shader = ImmediateModeRenderer20.createDefaultShader(false, true, 0); | |
} | |
public void push(Vector2 point, float dx) { | |
bufferCount = Math.min(bufferCount+1, MaxTailBufferCapacity); | |
// Shift | |
for (int i=bufferCount-1; i>0; i--) { | |
points[i] = new Vector2(points[i-1].x + dx, points[i-1].y); | |
} | |
points[0] = point; | |
this.generate(); | |
} | |
private void generate() { | |
if (bufferCount <= 0) { | |
return; | |
} | |
Vector2 o1 = new Vector2(); | |
Vector2 o2 = new Vector2(); | |
for (int i=1; i<=bufferCount-2; i++) { | |
unnamed(points[i-1], points[i], points[i+1], SnakeLineWidth/2, o1, o2); | |
buffer.put(2*i*TailVertexSize, o1.x); | |
buffer.put(2*i*TailVertexSize+1, o1.y); | |
buffer.put((2*i+1)*TailVertexSize, o2.x); | |
buffer.put((2*i+1)*TailVertexSize+1, o2.y); | |
} | |
buffer.put(0, points[0].x); | |
buffer.put(1, points[0].y); | |
buffer.put(TailVertexSize, points[0].x); | |
buffer.put(TailVertexSize+1, points[0].y); | |
buffer.put(2*(bufferCount - 1)*TailVertexSize, points[bufferCount-1].x); | |
buffer.put(2*(bufferCount - 1)*TailVertexSize+1, points[bufferCount-1].y); | |
buffer.put((2*(bufferCount - 1)+1)*TailVertexSize, points[bufferCount-1].x); | |
buffer.put((2*(bufferCount - 1)+1)*TailVertexSize+1, points[bufferCount-1].y); | |
if (bufferCount > 1) { | |
unnamed2(points[1], points[0], SnakeLineWidth/2, o1, o2); | |
buffer.put(0, o2.x); | |
buffer.put(1, o2.y); | |
buffer.put(TailVertexSize, o1.x); | |
buffer.put(TailVertexSize+1, o1.y); | |
} | |
} | |
// Vertex 2, Color 4 | |
public void draw(Camera camera) { | |
shader.begin(); | |
shader.setUniformMatrix("u_projModelView", camera.combined); | |
int loc = shader.getAttributeLocation(ShaderProgram.POSITION_ATTRIBUTE); | |
Gdx.gl20.glEnableVertexAttribArray(loc); | |
buffer.position(0); | |
Gdx.gl20.glVertexAttribPointer(loc, 2, GL20.GL_FLOAT, false, TailVertexSize*4, buffer); | |
shader.setAttributef(ShaderProgram.COLOR_ATTRIBUTE, color.r, color.g, color.b, color.a); | |
Gdx.gl20.glDrawArrays(GL20.GL_TRIANGLE_STRIP, 0, bufferCount * 2); | |
shader.end(); | |
} | |
private static void unnamed(final Vector2 p0, final Vector2 p1, final Vector2 p2, float d, Vector2 o1, Vector2 o2) { | |
Vector2 v0 = new Vector2(p0).sub(p1); | |
Vector2 v1 = new Vector2(p2).sub(p1); | |
float a = angle(v0, v1); | |
float x = d / (float)Math.sin(a/2); | |
float a2 = -a/2 + v0.getAngleRad(); | |
Vector2 n = new Vector2(x * (float)Math.cos(a2), x * (float)Math.sin(a2)); | |
o1.set(new Vector2(p1).add(n)); | |
o2.set(new Vector2(p1).sub(n)); | |
} | |
private static void unnamed2(final Vector2 p0, final Vector2 p1, float d, Vector2 o1, Vector2 o2) { | |
Vector2 v0 = new Vector2(p1).sub(p0); | |
Vector2 vp = new Vector2(-v0.y, v0.x); | |
vp.nor(); | |
o1.set(new Vector2(p1).mulAdd(vp, d)); | |
o2.set(new Vector2(p1).mulAdd(vp, -d)); | |
} | |
private static float angle(Vector2 v1, Vector2 v2) { | |
Vector2 a2 = new Vector2(v1).nor(); | |
Vector2 b2 = new Vector2(v2).nor(); | |
return (float) Math.atan2(a2.crs(b2), a2.dot(b2)); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment