Repeating parallax using Cocos2D on Android - android

I want to draw a infinitely repeating parallax using Cocos2D on Android.
Now, there are some solutions given to this problem in Objective C, but I'm stuck with my implementation in Android. I have tried using
CCSprite background = CCSprite.sprite("background_island.png");
CCTexParams params = new CCTexParams(GL10.GL_LINEAR,GL10.GL_LINEAR,GL10.GL_REPEAT,GL10.GL_REPEAT);
background.getTexture().setTexParameters(params);
But it only extends the background in 1 direction.
I guess I have to use 2 sprites, such that as soon as 1st finishes, the other starts and vice versa, but I'm stuck with the implementation.

I had the same problem and figured it out.
Try this. Declare the background and offset as a member:
CCSprite _bg;
float _bgOffset;
In your scene constructor:
CGSize winSize = CCDirector.sharedDirector().displaySize();
_bg = CCSprite.sprite("yourbg.png"); // needs to be square, i.e. 256x256
_bg.setTextureRect(0, 0, winSize.width, winSize.height, false);
_bg.getTexture().setTexParameters(GL10.GL_LINEAR, GL10.GL_LINEAR, GL10.GL_REPEAT,
GL10.GL_REPEAT);
_bg.setAnchorPoint(CGPoint.zero());
this.addChild(_bg);
And in your update(float dt) method:
if (_bgOffset > 2000000000)
_bgOffset = 0; // don't want problems, do we?
_bgOffset += dt * PIXELS_PER_SECOND; // this can be dynamic if you want
_bg.setTextureRect(0, _bgOffset, _bg.getTextureRect().size.width,
_bg.getTextureRect().size.height, false);
See "Repeating Backgrounds" in http://www.raywenderlich.com/3857/how-to-create-dynamic-textures-with-ccrendertexture for the Objective C code
If you need to go both ways, you could perhaps start with a non-zero _bgOffset and see if that works.
Hope this helps someone!

Please check out below link for Parallax vertical endless background: http://kalpeshsantoki.blogspot.in/2014/07/create-vertical-endless-parallax.html
CGSize winSize = CCDirector.sharedDirector().displaySize();
//I made graphics for screen 720*1200....so I made this dynamic scale to support multiple screens
float sX = winSize.width / 720.0f;
float sY = winSize.height / 1200.0f;
background = CCVerticalParallaxNode.node(sX, sY, true);
background.addEntity(1f, "background.png", 0);
background.addEntity(3, "road_simple.png", winSize.width / 2);
background.addEntity(1.7f, "road_side.png", 0);
addChild(background);

Related

Image sliding from left to right infinitely

I wish to have an animated background like this gif:
.
I don't have a mac or adobe after effects software to create a lottie json for such animation, and i want a more command over animation than simply using a gif. From what i have read over the internet, I have to use either TransitionManager or TranslationAnimation , but i am unable to figure out the correct code for it.
I am also interested in knowing if there is a plugin, or some way to make minor edits to already available lottie files like background color change , items color change, items removal, etc just like the way we could do for simple vector images(Using Android Studio, or at the very least, some free software). I found this lottie file which was doing a very great job for me, but i couldn't modify its colors
found it! When i logged the values of some variables like view.getX() or view.getRootView().getX(), i was able to figure out, that my view will have its location as 0,0 . so After that it was all a need for finding the screen size to finally make this infinite cloud moving animation. I am not sure if this function is good in terms of memory or performance , but on my device, its running smoothly.
private void showCloudMovingContinuouslyAnimation(View v) {
DisplayMetrics displayMetrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
int runtimeScreenWidth = displayMetrics.widthPixels;
int totalDuration = runtimeScreenWidth*5;
int viewPositionX = 0, viewPositionY = 0;
TranslateAnimation outToRight = new TranslateAnimation(
viewPositionX, (runtimeScreenWidth / 2f) + 50,
viewPositionY, viewPositionY);
outToRight.setDuration(totalDuration / 2);
outToRight.setRepeatCount(Animation.INFINITE);
TranslateAnimation inFromLeft = new TranslateAnimation(
-((runtimeScreenWidth / 2f) + 50), viewPositionX,
viewPositionY, viewPositionY
);
inFromLeft.setDuration(totalDuration / 2);
inFromLeft.setRepeatCount(Animation.INFINITE);
boolean shouldRemainThereAfterAnimationFinishes = true;// useful when animating for single time
AnimationSet animationSet=new AnimationSet(true);
animationSet.setInterpolator(new LinearInterpolator());
animationSet.setRepeatCount(Animation.INFINITE);
animationSet.addAnimation(inFromLeft);
animationSet.addAnimation(outToRight);
v.startAnimation(animationSet); // start animation
}

How to find out if game sprite is moving smoothly?

I'm making a simple jumping game for android using libgdx and box2d and I cannot figure out how to make sprites move really smooth. I have checked several articles regarding timestep fixing and synchronizing renderer and physics emulation, but none of the suggested ways really helped (http://gafferongames.com/game-physics/fix-your-timestep/).
Finally I decided to run the most simple test setting box2d world step equal to the framerate (which in case of stable fps should provide the best performance), but still movement is not totally smooth. I have tested on PC and on Android device, with stable 60-61 FPS. Here is pseudocode:
In render:
world.step(Gdx.graphics.getDeltaTime(), 6, 2);
stage.act();
stage.draw();
Stage basically has just one actor with act and draw overriden:
#Override
public void draw(Batch batch, float arg1) {
float x = this.getX() - width/2;
float y = this.getY() - height/2;
batch.draw(sprite, x, y, width, height);
}
#Override
public void act (float delta) {
...
//get body position
position = body.getPosition();
this.setPosition(position.x, position.y);
}
Actor has box2d body attached to it, there is no gravity and body's velocity is set constant:
BodyDef bodyDef = new BodyDef();
bodyDef.type = BodyType.DynamicBody;
bodyDef.position.set(world_position);
bodyDef.linearDamping = 0f;
bodyDef.angularDamping = 0f;
bodyDef.fixedRotation = true;
bodyDef.gravityScale = 0f;
...fixure added to the body
body.setLinearVelocity(0, -2f);
Camera is not moving, the case seems to be dead simple and yet sprite does not move exactly perfect. (Though it still looks smoother then when using time accumulator and interpolation)
Is it possible to achive absolutely smooth movement at all? Is there some mistake in my approach?
I have checked some similar games on the same android device - it seems that objects are moving absolutely smooth, but maybe it just seems so, because too many things happen on the screen and I don't have time to notice.
Any advice would be appreciated.
After further testing and researched I have figured out the problem - it was related not to FPS, but to pixel rounding. Box2d bodies have float coordinates - after converting them to round pixel values animation bemace much smoother.
How about to use CCPhysicsSprite instead of change position of sprite by time? You can use a batch, too. Just
sprite = [CCPhysicsSprite spriteWithTexture:batch.texture];
[batch addChild:sprite];
CCPhysicsSprite class
Example:
#import "CCPhysicsSprite.h"
CCPhysicsSprite *sprite = [CCPhysicsSprite spriteWithFile:#"sprite.png"];
[self addChild:sprite];
b2BodyDef bodyDef;
bodyDef.type = b2_dynamicBody;
bodyDef.position.Set(300/PTM_RATIO, 200/PTM_RATIO);
body = world->CreateBody(&bodyDef);
b2CircleShape circleShape;
circleShape.m_radius = 0.3;
b2FixtureDef fixtureDef;
fixtureDef.shape = &circleShape;
fixtureDef.density = 1;
fixtureDef.friction = 0.3f;
body->CreateFixture(&fixtureDef);
[sprite setPTMRatio:PTM_RATIO];
[sprite setB2Body:body];
[sprite setPosition: ccp(300, 200)];

Imprecise Box2d coordinates using LibGDX

I am using LibGDX and Box2d to build my first Android game. Yay!
But I am having some serious problems with Box2d.
I have a simple stage with a rectangular Box2d body at the bottom representing the ground, and two other rectangular Box2d bodies both at the left and right representing the walls.
A Screenshot
Another Screenshot
I also have a box. This box can be touched and it moves using applyLinearImpulse, like if it was kicked. It is a DynamicBody.
What happens is that in my draw() code of the Box object, the Box2d body of the Box object is giving me a wrong value for the X axis. The value for the Y axis is fine.
Those blue "dots" on the screenshots are small textures that I printed on the box edges that body.getPosition() give me. Note how in one screenshot the dots are aligned with the actual DebugRenderer rectangle and in the other they are not.
This is what is happening: when the box moves, the alignment is lost in the movement.
The collision between the box, the ground and the walls occur precisely considering the area that the DebugRenderer renders. But body.getPosition() and fixture.testPoint() considers that area inside those blue dots.
So, somehow, Box2d is "maintaining" these two areas for the same body.
I thought that this could be some kind of "loss of precision" between my conversions of pixels and meters (I am scaling by 100 times) but the Y axis uses the same technique and it's fine.
So, I thought that I might be missing something.
Edit 1
I am converting from Box coordinates to World coordinates. If you see the blue debug sprites in the screenshots, they form the box almost perfectly.
public static final float WORLD_TO_BOX = 0.01f;
public static final float BOX_TO_WORLD = 100f;
The box render code:
public void draw(Batch batch, float alpha) {
x = (body.getPosition().x - width/2) * TheBox.BOX_TO_WORLD;
y = (body.getPosition().y - height/2) * TheBox.BOX_TO_WORLD;
float xend = (body.getPosition().x + width/2) * TheBox.BOX_TO_WORLD;
float yend = (body.getPosition().y + height/2) * TheBox.BOX_TO_WORLD;
batch.draw(texture, x, y);
batch.draw(texture, x, yend);
batch.draw(texture, xend, yend);
batch.draw(texture, xend, y);
}
Edit 2
I am starting to suspect the camera. I got the DebugRenderer and a scene2d Stage. Here is the code:
My screen resolution (Nexus 5, and it's portrait):
public static final int SCREEN_WIDTH = 1080;
public static final int SCREEN_HEIGHT = 1920;
At the startup:
// ...
stage = new Stage(SCREEN_WIDTH, SCREEN_HEIGHT, true);
camera = new OrthographicCamera();
camera.setToOrtho(false, SCREEN_WIDTH, SCREEN_HEIGHT);
debugMatrix = camera.combined.cpy();
debugMatrix.scale(BOX_TO_WORLD, BOX_TO_WORLD, 1.0f);
debugRenderer = new Box2DDebugRenderer();
// ...
Now, the render() code:
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
camera.update();
world.step(1/45f, 6, 6);
world.clearForces();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
debugRenderer.render(world, debugMatrix);
}
Looks like the answer to that one was fairly simple:
stage.setCamera(camera);
I was not setting the OrthographicCamera to the stage, so the stage was using some kind of default camera that wasn't aligned with my stuff.
It had nothing to do with Box2d in the end. Box2d was returning healthy values, but theses values were corresponding to wrong places in my screen because of the wrong stage resolution.

android translateAnimation setDuration() doesn't work

I'm trying to create a translate animation to an imageView. The animation works but not according to the value I'm putting in the setDuration()
This is the code
/* flipping the images out of the screen */
float outOfScreenX = currentImageLocationX * DRAG_ACTION_SCREEN_BOUNDS_THREASHOLD;
float outOfScreenY = currentImageLocationY * DRAG_ACTION_SCREEN_BOUNDS_THREASHOLD;
translate = new TranslateAnimation(0, outOfScreenX, 0, outOfScreenY);
long velocity = Math.max(Math.abs((int) vTracker.getXVelocity()), Math.abs((int) vTracker.getYVelocity())) / 10;
velocity = (long) Math.min(velocity, 200);
translate.setDuration(velocity);
translate.setFillAfter(true);
mDragView.clearAnimation();
mDragView.startAnimation(translate);
imageStack.removeView(mOriginator);
The value of "velocity" derived from the vTracker, the speed of the user's touch on the view. It's always between 200-600 proximately, but the view moves much faster than this(and also a little flickering but this is another topic).

Android problem with Image Rotate and Matrix

Hopefully this is an easy one because I've been trying all sorts of different ways to get rid of this.
I am making an android app which incorporates a clock animation. I've got everything working really well except one very annoying thing.
I have a second hand on the clock and I'm using the following code to rotate it around a the second hand center point. As you'll probably notice I'm trying to make this look like an analogue second hand so it sweeps instead of just ticking.
public float secdegrees, secondwidth, secondheight;
secondMatrix = new Matrix();
secondwidth = secondHand.getWidth();
secondheight = secondHand.getHeight();
secdegrees = anglepersec * secnow;
secdegrees += anglepluspermilli * millis;
secondMatrix.setRotate(secdegrees, secondwidth/2, secondheight / 2);
newSecond = Bitmap.createBitmap(secondHand, 0, 0,
(int) secondwidth, (int) secondheight, secondMatrix, true);
c.drawBitmap(newSecond, (centrex - newSecond.getWidth()/2),
((face.getHeight()/2) - newSecond.getHeight()/2), null);
It actually does just the job I want... almost.
The problem is the hand shakes/jiggles around the center point ever so slightly, but it's really noticeable and really spoils the aesthetics.
I pretty much suspect that it's the way that it's rounding the float value, but I was hoping that someone had experienced this before and had any ideas on how to get rid of it.
For reference the second hand image was originally 74 px x 28 px and is (currently) 74 x 74 pixels .png with the middle of the second hand exactly crossing the crossing point. I've also tried making it 75 x 75 so that there is actually a central pixel too but no luck.
Any help at all would be appreciated.
** UPDATE
I've tried to change the code in case the decimals were getting dropped but still no luck I'm afraid. Here is option 2 I've tried and failed with;
secondMatrix = new Matrix();
secondwidth = secondHand.getWidth();
secondheight = secondHand.getHeight();
secdegrees = anglepersec * secnow;
secdegrees += anglepluspermilli * millis;
secondMatrix.setRotate(secdegrees, secondwidth/2, secondheight / 2);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, (int) secondwidth,
(int) secondheight, secondMatrix, true);
float secW = newSecond.getWidth()/2;
float secH = newSecond.getHeight()/2;
// NEW CODE HERE
float calcdeg = secdegrees % 90;
calcdeg = (float) Math.toRadians(calcdeg);
float NegY = (float) ((secondwidth*Math.cos(calcdeg)) +
(secondwidth * Math.sin(calcdeg)));
c.drawBitmap(newSecond, centrex - NegY/2,
((face.getHeight()/2) - NegY/2), null);
I understand your problem, I have never encountered it mysleft, but it sounds pretty obvious to me. Since the rotations changes the width and height of the image, your imprecision comes from centrex - NegX/2
I have not tested, but I suggest you try:
Matrix matrix=new Matrix()
//first translate to place the center of the hand at Point(0,0)
matrix.setTranslate(-secondWidth/2,-secondHeight/2);
matrix.setRotate(secdegrees);
//now place the pivot Point(0,0) at its expected location
matrix.setTranslate(centreX,centreY);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, secondWidth, secondHeight, matrix, false);
c.drawBitmap(newSecond,0,0,null);
Of course, this is suboptimal, since the newSecond bitmap is much larger than it actually needs to be. So if your centrex and centrey are big, you might want to translate less than that, and then draw with a translation of the difference.
//now place the pivot to a position where the hand can be fully drawn without imprecion on the future location of Point(0,0)
matrix.setTranslate(secondWith,secondHeight);
newSecond = Bitmap.createBitmap(secondHand, 0, 0, secondWidth, secondHeight, matrix, false);
c.drawBitmap(newSecond,centrex-secondWidth,centrey-secondHeight,null);
Hope this helps.

Categories

Resources