package com.gebauz.pingK.game;
import java.util.Vector;
import javax.microedition.khronos.opengles.GL10;
import android.util.Log;
import com.gebauz.framework.util.GLUtil;
import com.gebauz.framework.util.MathUtil;
import com.gebauz.framework.util.Mesh;
import com.gebauz.framework.util.Texture;
import com.gebauz.framework.util.Vector2;
import com.gebauz.framework.util.renderstates.BlendingStates.BlendingMode;
import com.gebauz.framework.util.renderstates.RenderStates;
import com.gebauz.pingK.R;
public class BallTrail
{
private class TrailElement
{
private Vector2 mPosition
;
private Vector2 mNormal
;
private Vector2 mDirection
;
private Vector2 mPoint1
;
private Vector2 mPoint2
;
private float mLifeTime = 0.0f
;
public TrailElement
(Vector2 pos, Vector2 prevPos,
float angleNormal
)
{
mPosition =
new Vector2
(pos.
x, pos.
y);
mDirection =
new Vector2
(pos.
x - prevPos.
x, pos.
y - prevPos.
y);
if (angleNormal
< 0.0f
)
{
mNormal =
new Vector2
(mDirection.
y, -mDirection.
x);
}
else
{
// 0
mNormal =
new Vector2
((float)Math.
cos(MathUtil.
degToRad(angleNormal
)),
(float)Math.
sin(MathUtil.
degToRad(angleNormal
)));
}
mNormal.
setLength(GameConsts.
BALL_TRAIL_WIDTH);
mPoint1 =
new Vector2
(mPosition.
x + mNormal.
x, mPosition.
y + mNormal.
y);
mPoint2 =
new Vector2
(mPosition.
x - mNormal.
x, mPosition.
y - mNormal.
y);
mLifeTime = 0.0f
;
}
public Vector2 getPosition
()
{
return mPosition
;
}
public Vector2 getDirection
()
{
return mDirection
;
}
public Vector2 getNormal
()
{
return mNormal
;
}
public Vector2 getPoint1
()
{
return mPoint1
;
}
public Vector2 getPoint2
()
{
return mPoint2
;
}
public void update
(float deltaTime
)
{
mLifeTime += deltaTime
;
}
public float getAlpha
()
{
return (1.0f-MathUtil.
clamp(mLifeTime / GameConsts.
BALL_TRAIL_ELEMENT_LIFETIME, 0.0f, 1.0f
));
}
}
private Ball mBall
;
private Mesh mTrailMesh =
new Mesh
();
private Texture mTexture =
new Texture
();
//private Vector<Vector2> mTrailPoints = new Vector<Vector2>();
private Vector<TrailElement
> mElements =
new Vector<TrailElement
>();
private int mNumPrimitives =
0;
private float mTrailTimer = 0.0f
;
//private float mTrailFadeTimer = 0.0f;
public BallTrail
(Ball ball
)
{
mBall = ball
;
mTexture.
loadTexture(R.
drawable.
trail);
}
public void reset
()
{
//mTrailPoints.clear();
mElements.
clear();
mTrailMesh.
setVertices(null);
mNumPrimitives =
0;
}
/**
* Add new trail point
* @param x X-axis coordinate
* @param y Y-axis coordinate
* @param angleNormal if >= 0.0f, specifies the angle of the normal to be used
*/
public void addTrailPoint
(float x,
float y,
float angleNormal
)
{
mTrailTimer -= GameConsts.
BALL_TRAIL_INTERVAL;
Vector2 lastPos =
new Vector2
(x, y
);
if (mElements.
size() > 0)
{
lastPos = mElements.
get(mElements.
size()-
1).
getPosition();
// do not add point if positions are the same
if (Vector2.
distance(lastPos,
new Vector2
(x, y
)) < MathUtil.
EPSILON)
{
return;
}
}
mElements.
add(new TrailElement
(new Vector2
(x, y
), lastPos, angleNormal
));
// trim if larger than wanted
while (mElements.
size() > GameConsts.
BALL_TRAIL_LENGTH)
{
mElements.
remove(0);
}
//mTrailFadeTimer = 0.0f;
buildGeometry
();
}
public void buildGeometry
()
{
// prepare geometry
if (mElements.
size() >=
2)
{
//float life = 1.0f - MathUtil.clamp(mTrailFadeTimer / 2.0f, 0.0f, 1.0f);
// two vertices per trail element
//float vertices[] = new float[mElements.size() * Mesh.COORD_ELEMENTS_COUNT * 6];
Mesh.
AttributeArray vertices =
new Mesh.
AttributeArray(mElements.
size() * Mesh.
COORD_ELEMENTS_COUNT * 2 * 2);
Mesh.
AttributeArray texCoords =
new Mesh.
AttributeArray(mElements.
size() * Mesh.
TEX_COORD_ELEMENTS_COUNT * 2 * 2);
Mesh.
AttributeArray colors =
new Mesh.
AttributeArray(mElements.
size() * Mesh.
COLOR_ELEMENTS_COUNT * 2 * 2);
for (int i = mElements.
size() -
1; i
>=
0; i--
)
{
TrailElement element1 = mElements.
get(i
);
vertices.
fill(element1.
getPoint1().
x, element1.
getPoint1().
y, 0.0f
);
vertices.
fill(element1.
getPoint2().
x, element1.
getPoint2().
y, 0.0f
);
texCoords.
fill(0.0f, 1.0f
);
texCoords.
fill(0.0f, 0.0f
);
/* float alpha = (float)i / (float)(mElements.size()-1);
alpha *= GameConsts.BALL_TRAIL_MAX_ALPHA;
alpha *= life;*/
float lifeTime = element1.
getAlpha();
if (i ==
0)
lifeTime = 0.0f
;
colors.
fill(1.0f, 1.0f, 1.0f, lifeTime
);
colors.
fill(1.0f, 1.0f, 1.0f, lifeTime
);
if (i
> 0)
{
TrailElement element2 = mElements.
get(i-
1);
if (Vector2.
dotProduct(element1.
getNormal(), element2.
getNormal()) < 0.0f
)
{
// facing away -> twist
vertices.
fill(element1.
getPoint2().
x, element1.
getPoint2().
y, 0.0f
);
vertices.
fill(element1.
getPoint1().
x, element1.
getPoint1().
y, 0.0f
);
texCoords.
fill(0.0f, 1.0f
);
texCoords.
fill(0.0f, 0.0f
);
colors.
fill(1.0f, 1.0f, 1.0f, lifeTime
);
colors.
fill(1.0f, 1.0f, 1.0f, lifeTime
);
}
}
}
mNumPrimitives = vertices.
getUsedCount() / Mesh.
COORD_ELEMENTS_COUNT;
mTrailMesh.
setPrimitiveType(GL10.
GL_TRIANGLE_STRIP);
mTrailMesh.
setVertices(vertices.
getAttributeArray());
mTrailMesh.
setTexCoords(texCoords.
getAttributeArray());
mTrailMesh.
setColors(colors.
getAttributeArray());
}
}
public void update
(float deltaTime
)
{
mTrailTimer += deltaTime
;
//mTrailFadeTimer += deltaTime;
if (mTrailTimer
> GameConsts.
BALL_TRAIL_INTERVAL)
{
addTrailPoint
(mBall.
getX(), mBall.
getY(), -1.0f
);
}
for (int i =
0; i
< mElements.
size(); i++
)
{
mElements.
get(i
).
update(deltaTime
);
}
}
public void updateFade
(float deltaTime
)
{
//mTrailFadeTimer += deltaTime;
for (int i =
0; i
< mElements.
size(); i++
)
{
mElements.
get(i
).
update(deltaTime
);
}
// rebuild geometry for color fading...
buildGeometry
();
}
public void render
()
{
GL10 gl = GLUtil.
getGL();
// transform
gl.
glMatrixMode(GL10.
GL_MODELVIEW);
gl.
glPushMatrix();
{
gl.
glLoadIdentity();
RenderStates renderStates = GLUtil.
getRenderStates();
renderStates.
depthTest.
setEnabled(false);
renderStates.
culling.
setEnabled(false);
renderStates.
blending.
setEnabled(true);
renderStates.
blending.
setBlendingMode(BlendingMode.
ALPHABLEND);
renderStates.
getTextureStage(0).
bindTexture(mTexture
);
renderStates.
activate();
mTrailMesh.
render(mNumPrimitives
);
//mTrailMesh.render();
renderStates.
deactivate();
renderStates.
getTextureStage(0).
bindTexture(null);
}
gl.
glPopMatrix();
}
}