How to change position of a moving body - Box2D - android

I currently have a body created that is Dynamic and moves at a constant speed with a Vector2(). What I want is for when the body leaves the edge of the screen, to come back from that current point back to its original point instantaneously. How do I do this?
a.applyForceToCenter(aMovement, true);
a.applyTorque(3000, true);
FixtureDef fDef = new FixtureDef();
BodyDef ballD = new BodyDef();
ballD.type = BodyType.DynamicBody;
//random location for asteroid
int aLoc = (int) (aLocation * 15);
float x = 300;
switch(aLoc)
{
case 0:
ballD.position.set(x, -105);
break;
case 1:
ballD.position.set(x, -95);
break;
case 2:
ballD.position.set(x, -80);
break;
case 3:
ballD.position.set(x, -65);
break;
case 4:
ballD.position.set(x, -50);
break;
case 5:
ballD.position.set(x, -35);
break;
case 6:
ballD.position.set(x, -20);
break;
case 7:
ballD.position.set(x, -5);
break;
case 8:
ballD.position.set(x, 10);
break;
case 9:
ballD.position.set(x, 25);
break;
case 10:
ballD.position.set(x, 40);
break;
case 11:
ballD.position.set(x, 55);
break;
case 12:
ballD.position.set(x, 70);
break;
case 13:
ballD.position.set(x, 85);
break;
default:
ballD.position.set(x, 0);
}
PolygonShape asteroid = new PolygonShape();
asteroid.setAsBox(12.5f, 12.5f);
//asteroid definition
fDef.shape = asteroid;
fDef.density = .5f;
fDef.friction = .25f;
fDef.restitution = .75f;
a = world.createBody(ballD);
a.createFixture(fDef);
a.setFixedRotation(false);
//asteroid image
aSprite = new Sprite(new Texture("img/asteroid-icon.png"));
aSprite.setSize(12.5f * 4, 12.5f * 4);
aSprite.setOrigin(aSprite.getWidth() / 2, aSprite.getHeight() / 2);
a.setUserData(aSprite);
asteroid.dispose();

You could use Body.setTransform() for that task, but I would not do that. setTransform() causes a lot of trouble in the long run.
For me it lead to weird bugs. For example using setTransform disabled my ContactFilter in random moments, which cost me several days of debugging until I found that.
Furthermore it causes non-physical behaviour, because you basically teleport the Body.
Better would be to destroy the Body completely and recreate a new one at the same initial position of the old one.

You can set the position of your Box2D a body instantly through this method:
a.setTransform(new_x, new_y, new_angle);
With this, you can create a condition that sets the x and y position of the body back to its original position when the x or y value of the body is outside of the screen.
if(outsideBounds()){
a.setTransform(start_x, start_y, start_angle);
}
You can check whether your object is offscreen by either checking its Box2D position and its converted screen coordinates, or by checking the sprite's location.
Once you've received the x and y screen positions, you can compare them to the screen bounds like this:
pos_x>screenWidth||pos_x<0||pos_y>screenHeight||pos_y<0
This can be improved by including the dimensions of the object, depending on when you want the transformation to happen:
(pos_x-objWidth)>screenWidth || (pos_x+objWidth)<0 ||
(pos_y-objHeight)>screenHeight || (pos_y+objHeight)<0

You can use the following:
body.setTransform(newX, newY, newAngle);
body.setAwake(true);
Waking up the body is important.
It might be currently inactive and without waking it up neither gravity nor any immediate collisions will affect it at the new position.

Related

How to rotate an image in Glide to be right side up

I am a little bit of a novice Android developer but I am working on a project to improve memory efficiency in our app's handling of images.
Right now, we have some code for rotating an image based on the Exif data to ensure that it's right side up. I'd like to do the same thing but in Glide, but I can't find any documentation on that... or even documentation on reading Exif data.
I have to imagine this is a fairly common use case! I'd like to take the following code and reduce it to a straightforward Glide method.
Here's what we have now:
final Matrix bitmapMatrix = new Matrix();
int widthMultiplier = 1;
int heightMultiplier = 1;
try {
Metadata metadata = ImageMetadataReader.readMetadata(new ByteArrayInputStream(bo.toByteArray()));
final Collection<ExifIFD0Directory> exifIFD0Directories = metadata.getDirectoriesOfType(ExifIFD0Directory.class);
if (exifIFD0Directories != null) {
for (ExifIFD0Directory d : exifIFD0Directories) {
if (d.containsTag(ExifIFD0Directory.TAG_ORIENTATION)) {
try {
final int exifOrientation = d.getInt(ExifIFD0Directory.TAG_ORIENTATION);
switch (exifOrientation) {
case 1:
break; // top left
case 2:
heightMultiplier = -1;
break; // top right
case 3:
bitmapMatrix.postRotate(180);
break; // bottom right
case 4:
bitmapMatrix.postRotate(180);
heightMultiplier = -1;
break; // bottom left
case 5:
bitmapMatrix.postRotate(90);
heightMultiplier = -1;
break; // left top
case 6:
bitmapMatrix.postRotate(90);
break; // right top
case 7:
bitmapMatrix.postRotate(270);
heightMultiplier = -1;
break; // right bottom
case 8:
bitmapMatrix.postRotate(270);
break; // left bottom
default:
break; // Unknown
}
break;
} catch (MetadataException e) {
handleException(e, subscriber, uri, inputStream, mFinalPath, fromGallery);
return;
}
}
}
}
} catch (ImageProcessingException | IOException e) {
handleException(e, subscriber, uri, inputStream, mFinalPath, fromGallery);
return;
}
Any ideas are appreciated.
From some additional resource, it sounds as if Glide actually handles this automatically.

How to apply multiple effect on GLSurfaceView in Android?

Here is my code which works fine
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BLACKWHITE);
mEffect.setParameter("black", .9f);
mEffect.setParameter("white", .5f);
break;
but now I want two effects on it, what to do ?
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_BLACKWHITE);
mEffect.setParameter("brightness", 2.0f);
I want to marge both effects with "grayscale image"
mEffect = effectFactory.createEffect(EffectFactory.EFFECT_GRAYSCALE);
I also look at this documents but no help [GLSurfaceView][1]
1: https://developer.android.com/reference/android/opengl/GLSurfaceView.html ,
EGLDisplay
1: https://developer.android.com/reference/android/opengl/EGLDisplay.html and Effect factory too

How to start Translate Animation in random order in Android?

I have 3 Translate Animation to be played when the app starts -
Animation animation = new TranslateAnimation(0, 0, -1500, 1500);
animation.setDuration(1000);
animation.setFillAfter(false);
myimage.startAnimation(animation);
animation.setRepeatCount(Animation.INFINITE);
Animation animation2 = new TranslateAnimation(0, 0, -1000, 1000);
animation2.setDuration(1000);
animation2.setFillAfter(false);
myimage2.startAnimation(animation2);
animation2.setRepeatCount(Animation.INFINITE);
Animation animation3 = new TranslateAnimation(0, 0, -500, 500);
animation3.setDuration(1000);
animation3.setFillAfter(false);
myimage3.startAnimation(animation3);
animation3.setRepeatCount(Animation.INFINITE);
I want to start the above 3 in random order, not necessarily the first one first.
One full day gone and I'm still unable to find a solution.
Any pointers on how to achieve it ?
You can generate random number in java and do switch
Random random = new Random();
int num = 3;
switch(random.nextInt(num)) {
case 0:
animateFirst();
break;
case 1:
animateSecond();
break;
case 2:
animateThird();
break;
}
This is one way I got, modifying your code, #Murtaza Hussain
switch(random.nextInt(num)) {
case 0:
animateFirst();
animateSecond();
animateThird();
break;
case 1:
animateSecond();
animateFirst();
animateThird();
break;
case 2:
animateFirst();
animateThird();
animateSecond();
break;
}

Android: DisplayMetrics densityDpi returns zero on rooted devices

Short problem
DisplayMetrics.densityDpi seems to be zero on rooted devices.
Long problem
I am using the following code in my app:
public static int getIconSize(Activity activity) {
int size;
DisplayMetrics metrics = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
switch (metrics.densityDpi) {
case DisplayMetrics.DENSITY_LOW:
size = 36;
break;
case DisplayMetrics.DENSITY_MEDIUM:
size = 48;
break;
case DisplayMetrics.DENSITY_TV:
size = 64;
break;
case DisplayMetrics.DENSITY_HIGH:
size = 72;
break;
case DisplayMetrics.DENSITY_XHIGH:
size = 96;
break;
case DisplayMetrics.DENSITY_400:
size = 120;
break;
case DisplayMetrics.DENSITY_XXHIGH:
size = 144;
break;
case DisplayMetrics.DENSITY_560:
size = 168;
break;
case DisplayMetrics.DENSITY_XXXHIGH:
size = 192;
break;
default:
size = (int) (metrics.densityDpi * (3/10));
}
return size;
}
I use this to scale icons being made by my app during runtime and scale icons I get from other apps, since they aren't always the right size.
This works great, but on (some) rooted devices it seems to fail. Size is returned as zero, so from the code, we can conclude that metrics.densityDpi must be equal to zero. (I don't have a rooted phone to test this)
I have looked into the <supports-screens> section of the manifest, but it seems like the default values are the ones I need.
Does anyone know the reason why this is happening and possibly a fix?
Thank you
Seems like rooted phones don't always return a value for densityDpi. I solved this by adding this at the end op the code in my question. density seems to be returned right.
if (size == 0) {
size = (int) (metrics.density * 48);
}

How to show different backgrounds at a time in andengine?

i am new developer on andengine. i am making a game of bike racer, where i want to move my background instead of my bike. so how can i use two 3 background if 1 background is complete then start second one and when it complete then start third? How should i do for it please tell me to solve this problem.
Are you using tiles in your background?
I got this snippet of code from : This very useful tutorial
switch(lDirection) {
case RIGHT:
int RightAnimTiles[] = {WorldActivity.RIGHT_CENTER_TILE - 1,
WorldActivity.RIGHT_CENTER_TILE,
WorldActivity.RIGHT_CENTER_TILE + 1,
WorldActivity.RIGHT_CENTER_TILE};
animate(WorldActivity.WALK_ANIMATE_DURATION, RightAnimTiles, -1);
break;
case DOWN:
int DownAnimTiles[] = {WorldActivity.DOWN_CENTER_TILE - 1,
WorldActivity.DOWN_CENTER_TILE,
WorldActivity.DOWN_CENTER_TILE + 1,
WorldActivity.DOWN_CENTER_TILE};
animate(WorldActivity.WALK_ANIMATE_DURATION, DownAnimTiles, -1);
break;
case LEFT:
int LeftAnimTiles[] = {WorldActivity.LEFT_CENTER_TILE - 1,
WorldActivity.LEFT_CENTER_TILE,
WorldActivity.LEFT_CENTER_TILE + 1,
WorldActivity.LEFT_CENTER_TILE};
animate(WorldActivity.WALK_ANIMATE_DURATION, LeftAnimTiles, -1);
break;
case UP:
int UpAnimTiles[] = {WorldActivity.UP_CENTER_TILE - 1,
WorldActivity.UP_CENTER_TILE,
WorldActivity.UP_CENTER_TILE + 1,
WorldActivity.UP_CENTER_TILE};
animate(WorldActivity.WALK_ANIMATE_DURATION, UpAnimTiles, -1);
break;
default:
break;
}

Categories

Resources