Removing animation logic from Render method in Libgdx - android

I want to delegate animations to a different class/entity so that render method is not bloated with code needed for animations. If the animation going on render method should execute that and move to its normal processing when the animation is done. Animation should except required sprites that involved in the animation. render method should render other sprites in normal way. (I am talking about animations of several sprites not sprite animations off of sprite sheet)
Is there a object oriented way to achieve this?
#Override
public void render ()
{
long ctime = System.currentTimeMillis();
Gdx.gl.glClearColor(backColor.r, backColor.g, backColor.b, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
float deltaTime = Gdx.graphics.getDeltaTime();
if(!startGame)
return;
if(camera != null)
batch.setProjectionMatrix(camera.combined);
batch.begin();
for (int i = 0; i < clusterList.size(); i++) {
clusterList.get(i).render(batch);
batch.end();
if(!isFinished)
scoreBar.setDeltaTime(deltaTime);
Gdx.gl.glEnable(GL20.GL_BLEND);
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA);
shapeRenderer.begin(ShapeRenderer.ShapeType.Filled);
shapeRenderer.setProjectionMatrix(batch.getProjectionMatrix());
shapeRenderer.setColor(Color.GRAY.r,Color.GRAY.g, Color.GRAY.b, 0.6f);
shapeRenderer.rect(0, camH - barHeight, camW, barHeight);
shapeRenderer.end();
Gdx.gl.glDisable(GL20.GL_BLEND);
batch.begin();
scoreBar.render(batch);
if (animateSpread) {
timeLoopSpread += deltaTime;
if (timeLoopSpread > duration) {
timeLoopSpread = 0;
animateSpread = false;
} else
animateCluster();
}
}
private void animateCluster() {
float factor = Interpolation.pow5Out.apply(timeLoopSpread /duration);
for (int index =0; index < clusterList.size(); index++) {
Cluster tempC = clusterList.get(index);
currentPos.set(tempC.endPos);
currentPos.sub(tempC.startPos);
currentPos.scl(factor);
currentPos.add(tempC.startPos);
tempC.setCenterPosition(currentPos);
}
}

Object oriented way to do this is to make the clusters animate themselves.
Instead of calling AnimateClusters() you would enable/disable them animating. Wherever you enable animateSpread you would call something like
for (int i = 0; i < clusterList.size(); i++) {
clusterList.get(i).spreadStart();
}
Then update each cluster in render(), each cluster would keep its own animation time.
for (int i = 0; i < clusterList.size(); i++) {
// update animation in there
clusterList.get(i).update(delta);
}
You could also stop the animation in the same way as it was started.

Related

Vector2 is off - libgdx/java

game.batch.begin();
for (Array obstacle_array123: obstacle_array) {
body = obstacle_array123;
for (Body bodies: body) {
if (bodies.getUserData() instanceof Array && bodies.isActive()) {
sprites_array = (Array)bodies.getUserData();
for (int fix_pos = 0; fix_pos < sprites_array.size; fix_pos++) {
sprite = sprites_array.get(fix_pos);
if (verts.size != 0) verts.removeRange(0, verts.size - 1);
f = bodies.getFixtureList().get(fix_pos);
s = (PolygonShape)f.getShape();
transform = bodies.getTransform();
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(new Vector2(tmp));
}
rotation_point.set((verts.get(0).x + verts.get(1).x + verts.get(2).x + verts.get(3).x) / 4, (verts.get(0).y + verts.get(1).y + verts.get(2).y + verts.get(3).y) / 4);
sprite.setPosition(rotation_point.x - sprite.getWidth() / 2, rotation_point.y - sprite.getHeight() / 2);
sprite.setRotation(bodies.getAngle() * MathUtils.radiansToDegrees);
sprite.draw(game.batch);
}
}
}
}
game.batch.end();
I have a game where my bodies are made from multiple square fixtures, so this is the code to render each square sprite on each square fixture.
2 problems - 1.st --> it only renders the first sprite in the array
2.nd --> if you look at the following loop (SOLVED)
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(new Vector2(tmp));
}
well it is apperantly different compared to
for (int i = 0; i < s.getVertexCount(); i++)
{
s.getVertex(i, tmp);
transform.mul(tmp);
verts.add(tmp);
}
The spawned coordinates in 2nd example are wrong for half width and half height of the square.
When I try to get the coordinated from both examples the numbers are the same, but when setting the sprite position, 2nd example goes off.
You should probably ask both questions separately, but to answer your second question, then they ARE different.
In the first one you add a new Vector2 to verts each time through the loop. So verts will end up holding a load of different Vector2's.
In the second one you add the same Vector2 to verts over and over again, so it will just have one Vector2 with the same value over and over again (remember Java is pass by reference).
Caveat - My answer assumes that verts is some sort of standard collection or a libgdx Array.

how render canvas on imageView to show circle moving faster (not jumping)

I have balls class extends ImageView
and on this i have Circle Ball going from left side to right side and in any time speed of Moving increased <
private void render() {
while (true) {
Thread.sleep(30);
if(x > getwidth()){
Step++ && x = 0;
}
x += step
}
}
private void update() {
while (true) {
Thread.sleep(60);
Postinvalidate();
}
}
any thing is Good but when step equals 20 and more < the ball do not movie Rightly and we see it jumping <
I testing the Step = 5 and Thread.sleep(value--) < but did not work Rightly
how can I Move the ball faster and render of onDraw was Rightly
TNX ALL < #};-

Update Canvas Preserving Old Canvas Details

Hi I'm developing a game in android, for that I have draw 8*8 rectangles using canvas.drawRect() method, now what I need is when user touches on any of the rect, its color has to change. For this I have done as follows.
public boolean onTouchEvent(final MotionEvent event) {
handleTouches(event.getX(), event.getY());
return false;
}
public void handleTouches(float x, float y) {
xLocTouch = (int) x;
yLocTouched = (int) y;
outerLoop: for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
if (GameView.tiles[i][j].rect.contains(xLocTouch, yLocTouched)) {
touched = true;
xTouched = i;
yTouched = j;
break outerLoop;
}
}
}
}
protected void onDraw(Canvas canvas) {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
canvas.drawRect(tiles[i][j].rect, paint);
canvas.drawRect(tiles[i][j].rect, p);
if(touched && i==xTouched && j == yTouched) {
Paint touchedColor = new Paint();
touchedColor.setColor(Color.BLUE);
canvas.drawRect(tiles[i][j].rect, touchedColor);
}
}
}
This code is works properly, but the problem is when I touch first time that rect's color changes, but for the second touch it erases old touches position. I need to keep all the touched rect as different color. Is there any way for this?
A Boolean array that tracks the touch state of each rectangle would do the trick. I can't see the external code, but this could be an additional field in your GameView class, and updated appropriately in your handleTouches method.
A perhaps less efficient, less elegant solution would be to just not set the color of the rectangle in onDraw if it's already Color.BLUE (modify your if statement appropriately). You can get the color of the touched pixel using this SE answer, but be forewarned you have to first turn the canvas into a bitmap in order to sample the color (hence the inefficiency).

libgdx opengl line quality improvement

How can i improve the quality of line drawn using openGL. I dont know if im doing this the best way . Im using ShareRenderer and line. But as you can see in the image round corners dont render very well.
Im getting points in touch down and drag, i thought this would be easy to draw a line but i guess this needs to done differently in openGL. I want to trace over letters with a finger for learning to write. I can use openGL-es 1 or 2 , doesn't matter. The device used here for the image was Samsung S3.
#Override
public void render(float delta) {
super.render(delta);
if(mPoints.size() < maxPoints) return;
shapeRenderer.begin(ShapeRenderer.ShapeType.Line);
for(int i=0; i < maxPoints-1; i++) {
Vector3 pnt = mPoints.get(i);
if(pnt.x == 0 && pnt.y == 0) continue;
Vector3 pnt2 = mPoints.get(i+1);
if(pnt2.x == 0 && pnt2.y == 0) continue;
shapeRenderer.line(pnt.x, pnt.y, pnt2.x, pnt2.y);
}
shapeRenderer.end();
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
shapeRenderer.setProjectionMatrix(getCamera().combined);
Gdx.gl20.glLineWidth(200);
Gdx.gl.glEnable(GL20.GL_BLEND);
}
#Override
public boolean touchDown(int x, int y, int pointer, int button) {
currentFinger = pointer;
if (++numStrokes >= 2) { //number of strokes for a letter
numStrokes = 0;
clearAllPoints();
currentPointIndex = 0;
}
setPoint(0, 0);
return false;
}
#Override
public boolean touchDragged(int x, int y, int pointer) {
if(currentFinger!=pointer) return false;
Vector3 pnt = mPoints.get(currentPointIndex);
tempVector.set(x, y, 0);
getCamera().unproject(tempVector);
float dx = Math.abs(tempVector.x - pnt.x);
float dy = Math.abs(tempVector.y - pnt.y);
if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
setPoint(x, y);
}
return false;
}
UPDATED render method below to draw filled rectangles and circles, filled circles works much better.
public void render(float delta) {
super.render(delta);
if(mPoints.size() < maxPoints) return;
shapeRenderer.begin(ShapeRenderer.ShapeType.FilledRectangle);
for(int i=0; i < maxPoints-1; i++) {
Vector3 pnt = mPoints.get(i);
if(pnt.x == 0 && pnt.y == 0) continue;
Vector3 pnt2 = mPoints.get(i+1);
if(pnt2.x == 0 && pnt2.y == 0) continue;
//This creates a rectangle from the set of points see : http://stackoverflow.com/questions/7854043/drawing-rectangle-between-two-points-with-arbitrary-width
dist.set(pnt2.x - pnt.x, pnt2.y - pnt.y, 0);
pVector.set(dist.y, -dist.x, 0); //Find perpendicular (right angle) to points , basically swap x and y , make one negative
float length = (float) Math.sqrt(pVector.x * pVector.x + pVector.y * pVector.y); //Thats length of perpendicular
normVector.set(pVector.x - length, pVector.y-length, 0);
//shapeRenderer.filledCircle(pnt.x, pnt.y, lineWidth);
shapeRenderer.filledRect(pnt.x - pVector.x * rectWidth/2 , pnt.y - pVector.y * rectWidth /2, rectWidth, rectWidth);
}
shapeRenderer.end();
}
OpenGL line width other than 1.0 is not well supported in OpenGL ES, so you should avoid it on Android (See Libgdx gl10.glLineWidth()).
To get a smoother, more rounded looking "fat lines", draw each touch point as a circle, and connect points that are more than a couple pixels apart with a rectangle.
See:
libgdx- pixmap: can I somehow change the width of the line?
Drawing rectangle between two points with arbitrary width
TO smoother any line or shape you can use feature of Multisample_anti-aliasing
to do this what you have to do is:
replace the parameters in Gdx.gl.glClear();
use this:
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT | (Gdx.graphics.getBufferFormat().coverageSampling?GL20.GL_COVERAGE_BUFFER_BIT_NV:0));
and in addition to this go to default packages like android html desktop etc and add this line
for android:
config.numSamples =2;
for ios:
config.multisample = GLKViewDrawableMultisample.valueOf("2");
for desktop:
config.samples = 3;
I am new to libGDX so i found this the easiest way to do it with any shape..

Drawing to the canvas on Android - screen flickering/tearing

I have an isometric map which I draw to the canvas. When I try and move the map around, these black lines flicker in between some of the tiles making the whole thing look rather shoddy.
Here is the relevant code from my updating thread
public void run() {
Canvas c;
while (isRunning){
c = null;
try {
c = cellMap.getHolder().lockCanvas(null);
synchronized (cellMap.getHolder()) {
cellMap.onDraw(c);
}
} finally {
if( c != null){
cellMap.getHolder().unlockCanvasAndPost(c);
}
}
}
}
and from my CellMap class (which extends SurfaceView):
public void onDraw(Canvas canvas){
canvas.drawColor(Color.BLACK);
int x = 0;
int y = 0;
for(int i = 0; i < mapSize; i++){
for(int j = 0; j < mapSize; j++){
x = (i-j) * 30 + xOffset;
y = (i+j) * 15 + yOffset;
mapCells[i][j].draw(canvas, paint, x, y);
}
}
mapCells[][] is an array of objects which contain the Bitmap image that needs to be drawn. The draw() function is only 1 line canvas.drawBitmap(bitmapImage, x, y, null)
I have discovered that removing the line Canvas.draw(Color.black) gets rid of the flicker. However, when I move the map the canvas is not cleared so I still see the image from the previous frames. I'd imagine it is because it is taking too long to draw the bitmaps? but the map is only very small at the moment.
I found the problem. When moving the map, the offset values were being changed. This lead to sections of the map being drawn temporarily with different offset values - creating the tearing. duh!
I solved this by copying the xOffset and yOffset values at the start of the onDraw() method, and using those values for the update.

Categories

Resources