box2d dynamic body is not falling under gravity - libgdx

I am trying to make a dynamic body which should move ahead a bit and then fall according to its gravity(as decided by the box2d engine). The problem is that right after moving upto a certain distance, instead of moving down, it is going up. This is the code i am using:
public class AngryBirdsTrajectoryPrototype implements ApplicationListener
{
private SpriteBatch spriteBatch;
private Texture backgroundTexture;
private Sprite backgroundSprite;
private static Sprite ball_in_hand;
private Texture ball_in_hand_Texture;
private static com.badlogic.gdx.physics.box2d.Body b2Body;
private com.badlogic.gdx.physics.box2d.World box2Dworld;
private boolean isBallShooted;
#Override
public void create() {
spriteBatch = new SpriteBatch();
Texture.setEnforcePotImages(false);
backgroundTexture = new Texture(Gdx.files.internal("angrybirds/background.png"));
backgroundTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
backgroundSprite = new Sprite(backgroundTexture);
backgroundSprite.setPosition(0, 0);
ball_in_hand_Texture = new Texture(Gdx.files.internal("test/ball_in_hand.png"));
ball_in_hand_Texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
ball_in_hand = new Sprite(ball_in_hand_Texture);
this.box2Dworld = new com.badlogic.gdx.physics.box2d.World(new Vector2(0.0F, 10.0F), true);
}
#Override
public void render() {
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 1f);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
if(!isBallShooted)
{
isBallShooted = true;
shoot(this.box2Dworld, 27.0F, 0.F);
}
box2Dworld.step(1.0f/60.0f, 6, 2);
spriteBatch.begin();
backgroundSprite.draw(spriteBatch);
Array<Body> bodies = new Array<Body>();
box2Dworld.getBodies(bodies);
for (Body body : bodies)
{
ball_in_hand.setPosition(30.0F * body.getPosition().x, 30.0F * body.getPosition().y);
Gdx.app.error("", "angleDegree= " + body.getAngle());
}
ball_in_hand.draw(spriteBatch);
spriteBatch.end();
}
#Override
public void dispose() {
spriteBatch.dispose();
backgroundTexture.dispose();
}
public static void shoot(com.badlogic.gdx.physics.box2d.World var1, float var2, float var3)
{
BodyDef var4 = new BodyDef();
var4.position.set(ball_in_hand.getX() / 30.0F, ball_in_hand.getY() / 30.0F);
var4.type = BodyType.DynamicBody;
var4.bullet = true;
var4.angularDamping = 0.5F;
b2Body = var1.createBody(var4);
CircleShape var6 = new CircleShape();
var6.setRadius(0.4F);
FixtureDef var7 = new FixtureDef();
var7.density = 0.8F;
var7.shape = var6;
var7.restitution = 0.7F;
var7.friction = 1.0F;
b2Body.createFixture(var7);
float var9 = var2 * 9.0F;
Vector2 var10 = new Vector2(var9 * (float)Math.cos((double)var3), var9 * (float)Math.sin((double)var3));
b2Body.applyForce(var10, b2Body.getWorldCenter(), true);
}
}
This is the output i am getting.
This is the output i want to achieve:
I have tried all possible options but none of them is working. Please help me. Thanks in advance.

Try this:
You should set your gravity to a negative number because of the Box2d coordinate system, like this:
enter code here`this.world = new World(new Vector2(0, -9.8f), true);
You should create a camera for your physics world and convert all your sizes to meters. For example, you can set 100 pixels = 1 meter in the box2d world, so you will need to set your camera's width and height in meters, too. Here is a full working example.
You can also get delta like this: Gdx.graphics.getDeltaTime()
Please let me know if it helped.

I think the problem in your code is in the create method:
this.box2Dworld = new com.badlogic.gdx.physics.box2d.World(new Vector2(0.0F, 10.0F), true)
You should use a negative value of gravity in y-direction like:
this.box2Dworld = new com.badlogic.gdx.physics.box2d.World(new Vector2(0.0F, -10.0F), true)
Also, please use debug-renderer to spot the error.

Related

How to scale down Texture in libgdx to fit smaller screens?

My app provides two buttons in a table row. Each image has a width of 300 pixel (source). The app shows all parts of both buttons if I provide an initial window width which is greater than 600. Even resizing the window to a smaller size works smoothly. Both buttons are shown fully and they get scaled down if needed when resizing the window. The buttons are cut off once I provide an initial window size which is smaller than 600 pixel. How can I show the whole buttons on small screens by default?
Screenshots:
My code looks like this:
public class LevelChooserState extends GameState {
private Stage stage;
private Texture bgTexture;
private Pixmap bgPixmap;
private Viewport viewportStage;
private Container<Table> container;
private Table table;
public LevelChooserState(final GameStateController gsc) {
super(gsc);
Gdx.app.log(TAG, "Setup Level Chooser State.");
// Setup Background Color
bgPixmap = new Pixmap(1, 1, Pixmap.Format.RGB565);
bgPixmap.setColor(Color.WHITE);
bgPixmap.fill();
bgTexture = new Texture(bgPixmap);
TextureRegionDrawable textureRegionDrawableBg = new TextureRegionDrawable(new TextureRegion(bgTexture));
// Setup viewports
viewportStage = new ExtendViewport(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
viewportStage.setScreenBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// Setup stage
stage = new Stage(viewportStage);
Gdx.input.setInputProcessor(stage);
// Setup font
int Help_Guides = 12;
int row_height = Gdx.graphics.getWidth() / 12;
FreeTypeFontGenerator generator = new FreeTypeFontGenerator(Gdx.files.internal("fonts/PatrickHand-Regular.ttf"));
FreeTypeFontGenerator.FreeTypeFontParameter parameter = new FreeTypeFontGenerator.FreeTypeFontParameter();
parameter.size = 30;
parameter.borderWidth = 1;
parameter.color = Color.BLACK;
BitmapFont myFont = generator.generateFont(parameter);
generator.dispose();
// Setup background pictures
TextureAtlas textureAtlas = new TextureAtlas("atlas/onoff.atlas");
TextureRegion backgroundTR1 = textureAtlas.findRegion("onoff_off");
TextureRegion backgroundTR2 = textureAtlas.findRegion("onoff_on");
// Setup TextButtons
TextureRegionDrawable up1= new TextureRegionDrawable(backgroundTR1);
TextureRegionDrawable down1= new TextureRegionDrawable(backgroundTR2);
TextureRegionDrawable checked1= new TextureRegionDrawable(backgroundTR2);
String text1 = "Deceptive dance in the poultry house.";
ClickListener clickListner1 = new ClickListener() {
#Override
public void clicked(InputEvent event, float x, float y) {
Gdx.app.log(Constants.TAG, "Button click received.");
gsc.setState(GameStateController.State.PLAY);
}
};
TextButton textButton1 = createTextButton(myFont, text1, up1, down1, checked1, clickListner1);
// ... created some more buttons at this point
// Setup Layout
container = new Container<Table>();
container.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
container.setBackground(textureRegionDrawableBg);
container.align(Align.bottomLeft);
table = new Table();
table.setBounds(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
table.setTouchable(Touchable.enabled);
table.setDebug(true);
table.debugAll();
table.setBackground(textureRegionDrawableBg);
table.setFillParent(true);
table.align(Align.top);
// TODO take care of scaling too when setting padding
float padding = 10;
table.row();
table.add(textButton1).expandX().pad(padding);
table.add(textButton2).expandX().pad(padding);
table.row();
table.add(textButton3).expandX().pad(padding);
table.add(textButton4).expandX().pad(padding);
table.row();
container.setActor(table);
stage.addActor(container);
}
private TextButton createTextButton(BitmapFont font, String text, TextureRegionDrawable up, TextureRegionDrawable down, TextureRegionDrawable checked, ClickListener clickListener) {
Label.LabelStyle labelStyle = new Label.LabelStyle();
labelStyle.font = font;
Label label = new Label(text,labelStyle);
label.setWrap(true);
TextButton.TextButtonStyle style = new TextButton.TextButtonStyle();
style.up = up;
style.down = down;
style.checked = checked;
style.font = font;
TextButton button = new TextButton(label.toString(), style);
//button.setSize(50,100);
button.setLabel(label);
button.getLabelCell().pad(20f);
button.getLabel().setAlignment(Align.topLeft);
button.setPosition(0,0);
button.addListener(clickListener);
return button;
}
#Override
public void update(float delta) {
}
#Override
public void render() {
Gdx.gl.glClearColor(1f,1f,1f,1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
stage.getViewport().apply();
stage.draw();
stage.act();
batch.end();
}
#Override
public void dispose() {
Gdx.app.log(TAG, "dispose(); Level Chooser");
stage.dispose();
bgPixmap.dispose();
bgTexture.dispose();
}
#Override
public void resize(int w, int h) {
Gdx.app.log(TAG, "resize() LevelChooserState;");
stage.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight(), true);
container.setFillParent(true); // makes sure the container will expand on resize
}
}
LibGDX uses real-pixel-to-screen-pixel mapping.
You're using an ExtendViewport to initialize the game, which takes its minimum height and width from the actual window size in Gdx.graphics.getWidth(), Gdx.graphics.getHeight().
This means that the 'fake screen' you have, which you can then resize as much as you want, is actually determined by the size of the window.
I would advise you start with a fixed size for the ExtendViewport - say, 600 width, 400 height - and later you can change this to suit different sizes if necessary.
ExtendViewport with fixed sizes works fantastically well, even when displaying on extremely large screens.
It works smoothly once I calculate and set the desired button manually. Width and height are calculated depending on screen size.
I changed this:
table.add(textButton1).expandX().pad(padding);
to this:
float buttonWidth = Gdx.graphics.getWidth()/2 * 0.9f;
float buttonHeight = buttonWidth * 1.3f;
table.add(textButton1).width(buttonWidth).height(buttonHeight).expandX().pad(padding);

Screen Display not proper on some screens Libgdx

I am developing a game in which i am making a Game Over Screen but the components are not rearranging properly.
What i am Getting on 1024 * 720 screen is:
and what it should look like:
and the code is:
#Override
public void show() {
stage = new Stage(new ScreenViewport());
camera = new OrthographicCamera(Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
Gdx.input.setInputProcessor(stage);
font = new BitmapFont(Gdx.files.internal("newfont.fnt"));
verysmallfont = new BitmapFont(Gdx.files.internal("verysmallfont.fnt"));
smallfont = new BitmapFont(Gdx.files.internal("smallfont.fnt"));
atlas = new TextureAtlas("ui/buttons.pack");//add atlas
skin = new Skin(atlas);
table = new Table(skin);
actiontable = new Table(skin);
actionbar = new Table(skin);
actionbar2 = new Table(skin);
table.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
actiontable.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
actionbar.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
actionbar2.setBounds(0,0,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
TextButton.TextButtonStyle buttonback = new TextButton.TextButtonStyle();
buttonback.up = skin.getDrawable("back");
buttonback.pressedOffsetX = 1;
buttonback.pressedOffsetY = -1;
buttonback.font = font;
buttonBack = new TextButton("",buttonback);
TextButton.TextButtonStyle lifebuttonstyle = new TextButton.TextButtonStyle();
lifebuttonstyle.up = skin.getDrawable("life");
lifebuttonstyle.pressedOffsetX = 1;
lifebuttonstyle.pressedOffsetY = -1;
lifebuttonstyle.font = font;
buttonlife = new TextButton("",lifebuttonstyle);
TextButton.TextButtonStyle textButtonStyle = new TextButton.TextButtonStyle();
textButtonStyle.up = skin.getDrawable("heart_game_continue");
textButtonStyle.pressedOffsetX = 1;
textButtonStyle.pressedOffsetY = -1;
textButtonStyle.font = font;
buttonPlay = new TextButton("",textButtonStyle);
TextButton.TextButtonStyle adsfreeStyle = new TextButton.TextButtonStyle();
adsfreeStyle.up = skin.getDrawable("Video");
adsfreeStyle.pressedOffsetX = 1;
adsfreeStyle.pressedOffsetY = -1;
adsfreeStyle.font = font;
buttonVideo = new TextButton("",adsfreeStyle);
TextButton.TextButtonStyle sharebuttonStyle = new TextButton.TextButtonStyle();
sharebuttonStyle.up = skin.getDrawable("Replay");
sharebuttonStyle.pressedOffsetX = 1;
sharebuttonStyle.pressedOffsetY = -1;
sharebuttonStyle.font = font;
buttonReplay = new TextButton("",sharebuttonStyle);
Label.LabelStyle headingstyle = new Label.LabelStyle(font,Color.WHITE);
label = new Label("Game Over",headingstyle);
label.setFontScale(1.7f);
Label.LabelStyle contstyle = new Label.LabelStyle(smallfont,Color.WHITE);
cont = new Label("Continue?",contstyle);
cont.setFontScale(2f);
Label.LabelStyle replaystyle = new Label.LabelStyle(verysmallfont,Color.WHITE);
replay = new Label("Replay",replaystyle);
shortVideo = new Label("(Short Video)",replaystyle);
replay.setFontScale(2f);
shortVideo.setFontScale(2f);
table.align(Align.top);
table.padTop(197f);
table.add(label);
table.getCell(label).spaceBottom(150f);
table.row();
table.add(cont);
table.getCell(cont).spaceBottom(80f);
table.row();
table.add(buttonPlay).size(200f,200f);
actiontable.add(buttonVideo).size(200f,200f);
actiontable.add(buttonReplay).size(200f,200f);
actiontable.align(Align.bottom);
actiontable.getCell(buttonVideo).spaceBottom(20f).padRight(100f);
actiontable.getCell(buttonReplay).spaceBottom(20f).padLeft(100f);
actiontable.row();
actiontable.add(shortVideo).padRight(100f);
actiontable.add(replay).padLeft(100f);
actiontable.padBottom(197f);
actiontable.setFillParent(true);
actionbar.align(Align.topLeft).setWidth(Gdx.graphics.getWidth());
actionbar.add(buttonBack).align(Align.left).size(90f,90f);
actionbar2.align(Align.topRight);
actionbar2.add(buttonlife).align(Align.right).size(90f,90f);
actionbar.getCell(buttonBack).pad(43f);
actionbar2.getCell(buttonlife).align(Align.right).pad(43f);
stage.addActor(actionbar2);
stage.addActor(actionbar);
stage.addActor(table);
stage.addActor(actiontable);
buttonPlay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener()).setScreen(new Main(level,a,start,sweep,collide,innerarcs,out,mid,arcsleft,left,pointerColor));
};
});
buttonReplay.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
int total = out+mid+innerarcs;
((Game) Gdx.app.getApplicationListener()).setScreen(new Main(level,a,total,pointerColor));
}
});
buttonBack.addListener(new ClickListener(){
#Override
public void clicked(InputEvent event, float x, float y) {
((Game) Gdx.app.getApplicationListener()).setScreen(new Menu(level));
}
});
}
SpriteBatch batch;
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0.184f,0.184f,0.184f,1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
stage.draw();
}
private OrthographicCamera camera;
#Override
public void resize(final int width, final int height) {
table.setTransform(true);
table.setSize(width,height);
actiontable.setTransform(true);
actiontable.setSize(width,height);
actionbar.setTransform(true);
actionbar.setSize(width,height);
}
I am new to libgdx please help i dont have any knowledge about how to use camera and viewports.
Thanks in advance..
€dit: sorry my bad - there's nothing like "stage.resize"
But I'll let the answer in, because it'll fix your problem, though not as fast as you wish, but in a more clear way.
(THE FOLLOWING TEXT IS NOT NECESSARRY FOR THE ANWSER AND ARE ONLY SUGGESTIONS)
(if you follow the following steps, you'll save yourself time & headaches in the future)
I'd suggest a viewport, because they'll kill many problems with scaling, and there are quite a few, from which you can choose, as you need.
LibGdx Viewports
A viewport takes care for different screen sizes with the help from different techniques (e.g. scaling, black bars)
Additionally a viewport is SUPER easy to implement.
You'll do the following(e.g. FitViewport(stretches content, if necessary)):
stage = new Stage();
OrthographicCamera cam = new OrthographicCamera();
cam.setToOrtho(false, 800, 600);
stage.setViewport(new FitViewport(800, 600, cam));
TADA. You implemented a viewport. Was not so hard.
(but make sure to call stage.getViewport().update(w, h) in the resize(w, h) method!! AND DON'T FORGET IT!!)
Second suggestion I'd do is:
Use a main table.
So you do following
Table myMothershipTable = new Table();
myMothershipTable.setFillParent(true);
myMothershipTable.add(add);
myMothershipTable.add(all);
myMothershipTable.add(content);
stage.addActor(myMothershipTable);
Now you've only one actor, which is the table, and you can be damned sure, that this table will fill the whole screen.
Your screen is 10999x3? yeah. the table will be 10999x3.
Good. If you've refactored your whole stuff into one table I'd suggest the next step:
stage.setDebugAll(true); //this will help you to see the actual buildup from your actors & elements
So heres the why:
The viewport takes care for your stage size
the single table makes sure, that your complete content will be within the screen ==> now you can add one item after another, and make sure with..
stage.setDebugAll(true).. that your content is placed properly.
If you follow this simple steps, you'll save yourself a lot of time and headache with designing the UI.

Units conversion Box2D with weird results

i'm using LibGDX and trying to learn box2D, but this units conversions are confusing me, what i think: i got a 256x256 pixels image and want to create a body representing this image, using the 1:32 scale, so everytime i want to pass values to the box2D scale i must divide it by 32 or mutiply by 1/32(it's the same equation), and everytime i want to get values from this world to pixel scale i must mutiply it by 32, but the problems still the same: can't get good simulations, i'll put my code here for you see how i'm doing things(i'll put the variables too so you can just ctrl+c and ctrl+v):
private SpriteBatch batch;
private ShapeRenderer srender;
private Texture img;
private World world;
private Body bad, bridge;
private OrthographicCamera cam, cam2;
private Box2DDebugRenderer render;
#Override
public void create () {
srender = new ShapeRenderer();
batch = new SpriteBatch();
img = new Texture("badlogic.jpg");
cam = new OrthographicCamera(500f, 500f);
cam.translate(250f, 250f);
cam.update();
//Used to draw the box2D world scaled to the pixels size
cam2 = new OrthographicCamera(500 * 0.03125f, 500 * 0.03125f);
cam2.translate(250f * 0.03125f, 250f * 0.03125f);
cam2.update();
render = new Box2DDebugRenderer();
world = new World(new Vector2(0f, -10f), true);
BodyDef bdef = new BodyDef();
bdef.type = BodyType.DynamicBody;
bad = world.createBody(bdef);
PolygonShape pshape = new PolygonShape();
pshape.setAsBox(img.getWidth() * 0.03125f, img.getHeight() * 0.03125f);
FixtureDef fdef = new FixtureDef();
fdef.shape = pshape;
bad.createFixture(fdef);
/*Criando a ponte*/
bdef.type = BodyType.StaticBody;
bridge = world.createBody(bdef);
pshape.setAsBox(500f * 0.03125f, 5f * 0.03125f);
bridge.createFixture(fdef);
bad.setTransform(new Vector2(250f * 0.03125f, 500f * 0.03125f) , 0);
bridge.setTransform(new Vector2(250f * 0.03125f, 0f * 0.03125f), 0);
batch.setProjectionMatrix(cam.combined);
srender.setProjectionMatrix(cam.combined);
}
#Override
public void render () {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
batch.draw(img, (bad.getPosition().x - img.getWidth()/2 * 0.03125f) * 32,
(bad.getPosition().y - img.getHeight()/2 * 0.03125f) * 32);
batch.end();
render.render(world, cam2.combined);
srender.begin(ShapeRenderer.ShapeType.Filled);
srender.circle(250f, 500f, 5f);
srender.circle(250f, 0f, 5f);
srender.end();
world.step(1/60f, 6, 2);
}
if you run this code you will see that the box created still not fitting the image size, the image stop walking on the middle of the screen while it should stop only at the bottom, can anyone help me here? thanks for attention.
Ps:i have already heard about changing the viewport, but i'm still trying to learn this conversions, after that i'll go look for the viewports.

Why can't this code produce a points layer in GeoTools

I am testing adding a collection of points to a map utilizing the Geotools API. I've been following this example as best I could Problem creating a point and adding it to FeatureCollection, as the example code is old, and things like FeatureCollections is deprecated. I tried using DefaultFeatureCollection instance instead, and I am not sure if I am using it correctly, and that is why the points do not appear on the map. What am I doing wrong? Here is some of my code:
private void plotMarkers() {
final SimpleFeatureType TYPE = this.createFeatureType();
final SimpleFeatureBuilder BLDR = new SimpleFeatureBuilder(TYPE);
DefaultFeatureCollection features = new DefaultFeatureCollection();
// arbitrary start position
Coordinate pos = new Coordinate(0, 0);
final double pointSpacing = 1.0;
String title = "Test";
features.add(creatureFeature(BLDR, pos, title));
// display points on screen
Style style = SLD.createPointStyle("circle", Color.RED, Color.RED, 1.0f, 5.0f);
Layer layer = new FeatureLayer(features, style);
this.getMapContent().addLayer(layer);
}
Maybe this can help you to make it work
private MapContent map;
private static Style pointStyle = SLD.createPointStyle("Circle", Color.RED, Color.RED, 0.5f, POINT_SIZE);
public static void CreatePoints(double X, double Y){
createPointLayer();
createFeatures(X,Y);
}
static void createFeatures(double X, double Y) {
Point point = geometryFactory.createPoint(new Coordinate(X, Y));
pointCollection.add(SimpleFeatureBuilder.build(pointType, new Object[]{point}, null));
//create map layer event
MapLayerEvent mple = new MapLayerEvent(pointLayer, MapLayerEvent.DATA_CHANGED);
//create maplayer list event
MapLayerListEvent mplle = new MapLayerListEvent(map, pointLayer, map.layers().indexOf(pointLayer), mple);
okvir.mapPane.layerChanged(mplle);
System.out.println(MessageFormat.format("Created Point: {0}", point));
}
private static void createPointLayer() {
if (pointType == null) {
pointFeatureTypeBuilder.setName("PointCreated");
pointFeatureTypeBuilder.setCRS(map.getCoordinateReferenceSystem());
pointFeatureTypeBuilder.add("the_geom", Point.class);
pointType = pointFeatureTypeBuilder.buildFeatureType();
pointCollection = new DefaultFeatureCollection(null, pointType);
}
pointLayer = new FeatureLayer(pointCollection, pointStyle);
map.addLayer(pointLayer);
}

libGDX 1.4.1 can't slow down animations

This is what I have:
...
private Array<Sprite> fireballFadeOutAnim;
private Array<Sprite> bucketFadeOutAnim;
private TextureAtlas fballAnimSheet;
private TextureAtlas bucketAnimSheet;
private Animation catch_animation;
private Animation visual_feedback;
private float elapsedTime = 0f;
...
#Override
public void create () {
...
fballAnimSheet = new TextureAtlas("animations/fireball_fadeout.txt");
bucketAnimSheet = new TextureAtlas("animations/bucket_fadeout.txt");
fireballFadeOutAnim = fballAnimSheet.createSprites("fireball_fadeout");
bucketFadeOutAnim = bucketAnimSheet.createSprites("bucket_fadeout");
catch_animation = new Animation(1/15f, fballAnimSheet.getRegions(), Animation.PlayMode.NORMAL);
visual_feedback = new Animation(1/15f, bucketAnimSheet.getRegions(), Animation.PlayMode.LOOP);
...
}
#Override
public void render () {
...
// Set the anim_elipsed_time
elapsedTime += Gdx.graphics.getDeltaTime();
...
// I try to draw them later on (under the render method) like this:
// Start and draw animation of fireball catch
batch.begin();
batch.draw(catch_animation.getKeyFrame(elapsedTime, true), fireBallRect.getX(), fireBallRect.getY());
batch.end();
}
I can see both animations happening extremely fast (they look like a white-flash), they do not loop even if the animation mode is set to "LOOP".
What am I doing wrong ? I can't seem to be able to slow them down or to have them LOOP. Thanks much.
Edited:
As requested, I upload all the code
public class MainActivity extends ApplicationAdapter {
public enum State {
PAUSE,
RUN,
RESUME,
STOPPED
}
public static State state = State.RUN;
private SpriteBatch batch;
private OrthographicCamera camera;
private Stage stage;
private Texture backgroundImage;
private Texture bucketImage;
private Texture fireballImage;
private Texture heart;
private TextureRegion criticalTexture;
private Sprite backgroundSprit;
private Sprite bucketSprite;
private Sprite fireballSprite;
private Sprite heartSprite;
private Rectangle bucketRect;
private Rectangle fireBallRect;
private Rectangle bucketSpriteRect;
private ShapeRenderer bucketRenderer;
private ShapeRenderer fireballRenderer;
private Button pauseButton;
private Array<Rectangle> fireballArray;
private Skin progressBarSkin;
private long lastFireballTime;
public static Sound bucket_tap;
public static Sound bucket_drag;
private Sound fireball_missed_sound;
private Sound catchFireball;
private Sound pauseBtnSound;
private Music bgMusic;
private float volume = 0.30f; // music and sfx volume control
public static int w;
public static int h;
private int barLength = 325;
private int numberOfFails = 10; // change numberOfFails to increase or decrese
// the total num. of missed fireballs the player
private int deductedBarSegment = barLength / numberOfFails;
private int numOfBallsLeft = numberOfFails; // use this var to check how many fballs left
private long fireballFrequency = 1000000000L; // change fireballFrequency to increase or decrease
// the number of fireballs on the screen
private int fireballSpeed = 400; // change the fireballSpeed to increase or decrease
// the speed at which the fireballs fall
private InputProcessor gameInputProcessor; // this sets the game input controller for the bucket
private InputMultiplexer multiplexer; // this sets the input processors from the game and UI
/************************************ Animation Properties ************************************/
private TextureAtlas fballAtlas;
private TextureAtlas bucketAtlas;
private Animation catch_animation;
private Animation visual_feedback;
private float elapsedTime = 0f;
private Actor feedbackPanel;
/**********************************************************************************************/
#Override
public void create () {
// Parse Test
//ParseObject testObject = new ParseObject("TestObject");
//testObject.put("foo", "bar");
//testObject.saveInBackground();
// Catch the dynamic size of the screen based on the device that's ran on
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
// Set up the camera
camera = new OrthographicCamera();
camera.setToOrtho(false, (float)w, (float)h);
// Instantiate the batch
batch = new SpriteBatch();
/***************************** These renders are for debugging only *****************************/
bucketRenderer = new ShapeRenderer();
fireballRenderer = new ShapeRenderer();
/**************************************************************************************************/
/******************************************** Stage and HUD ***************************************/
stage = new Stage();
pauseButton = new Button(new TextureRegionDrawable(
new TextureRegion(new Texture(Gdx.files.internal("images/pase_button_red.png")))),
new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("images/pase_button_white.png")))));
pauseButton.setX(flipCoordinates(w, 150));
pauseButton.setY(flipCoordinates(h, 170));
pauseButton.act(Gdx.graphics.getDeltaTime());
stage.addActor(pauseButton);
pauseButton.addListener(new ChangeListener() {
#Override
public void changed (ChangeEvent event, Actor actor) {
// Do something when the pauseButton is pressed
// Control multiple touches on the pauseButton
if(state == State.RUN) {
state = State.PAUSE;
pauseBtnSound.play();
// Set the pauseButton icon to the white version
//pauseButton.setColor(Color.WHITE);
}
else {
state = State.RUN;
pauseBtnSound.play();
}
}
});
// Add the critical_life indicator to the stage as an actor
criticalTexture = new TextureRegion(new Texture(Gdx.files.internal("images/critical_life.png")));
feedbackPanel = new Actor() {
public void draw(Batch batch, float alpha) {
batch.draw(criticalTexture, getX(), getY(), getOriginX(), getOriginY(), getWidth(), getHeight(),
getScaleX(), getScaleY(), getRotation());
}
};
feedbackPanel.setBounds(w / 2, h / 2,
criticalTexture.getRegionWidth(), criticalTexture.getRegionHeight());
// Set up an Action for the critical life actor
feedbackPanel.addAction(forever(sequence(scaleTo(2, 2, 0.5f), scaleTo(1, 1, 0.5f), delay(0.5f))));
feedbackPanel.act(Gdx.graphics.getDeltaTime());
stage.addActor(feedbackPanel);
/**************************************************************************************************/
/*********************************** Set up the Input Controllers *********************************/
// The multiplexer helps target several input processes (in this case, the stage and the
// InputProcessor.class)
multiplexer = new InputMultiplexer();
multiplexer.addProcessor(stage);
multiplexer.addProcessor(new GameInputProcessor());
// InputAdaptor
Gdx.input.setInputProcessor(multiplexer);
/**************************************************************************************************/
backgroundImage = new Texture("images/bg.jpg");
bucketImage = new Texture("images/bucket_small.png");
fireballImage = new Texture("images/fireball_small.png");
heart = new Texture("images/heart.png");
/*************************************** Animations Setup *****************************************/
fballAtlas = new TextureAtlas("animations/fireball_fadeout.txt");
bucketAtlas = new TextureAtlas("animations/bucket_fadeout.txt");
catch_animation = new Animation(0.50f, fballAtlas.getRegions());
visual_feedback = new Animation(0.15f, bucketAtlas.getRegions());
/**************************************************************************************************/
// Instantiate all sounds
bucket_tap = Gdx.audio.newSound(Gdx.files.internal("sounds/bucket_tap.ogg"));
bucket_drag = Gdx.audio.newSound(Gdx.files.internal("sounds/bucket_drag.ogg"));
fireball_missed_sound = Gdx.audio.newSound(Gdx.files.internal("sounds/fireball_missed.ogg"));
catchFireball = Gdx.audio.newSound(Gdx.files.internal("sounds/fastSteam.ogg"));
pauseBtnSound = Gdx.audio.newSound(Gdx.files.internal("sounds/pauseBtn_sound.ogg"));
bgMusic = Gdx.audio.newMusic(Gdx.files.internal("sounds/music_bg.mp3"));
bgMusic.setLooping(true);
bgMusic.play(); // <----------- turn bg music on/off
// Instantiate the progressBarSkin
progressBarSkin = new Skin();
progressBarSkin.add("progressBarBg", new Texture("images/progress-bar_bg.png"));
progressBarSkin.add("progressBar", new Texture("images/progress-bar_dynamic_red.png"));
// Create bg sprite
backgroundSprit = new Sprite(backgroundImage);
//backgroundSprit.setPosition((float)w / 2, (float)h / 2);
//backgroundSprit.setSize((float)w, (float)h);
// Bucket sprite
bucketSprite = new Sprite(bucketImage);
// Fireball sprite
fireballSprite = new Sprite(fireballImage);
// Heart sprite
heartSprite = new Sprite(heart);
// Set the bucketRect into the rect from the bucketSprite (THE GREEN ONE)
bucketSpriteRect = bucketSprite.getBoundingRectangle();
bucketSpriteRect.x = w / 2 - 100 / 2;
bucketSpriteRect.y = 20;
bucketSpriteRect.setSize(200, 200);
// Set the collision rectangle (THE RED ONE)
bucketRect = new Rectangle();
bucketRect.x = bucketSpriteRect.getX() + 70; // <---- adjust position left/right
bucketRect.y = bucketSpriteRect.getY() + 150; // <---- adjust position up/down
bucketRect.setSize(100, 10);
// Set a rectangle for each fireball sprite (THE WHITE ONE)
fireBallRect = new Rectangle();
fireBallRect.x = fireballSprite.getX();
fireBallRect.y = fireballSprite.getY();
fireBallRect.width = 55;
fireBallRect.height = 55;
fireballArray = new Array<Rectangle>();
}
#Override
public void render () {
// Devide the Render method into a few switch cases based on the game's state
switch (state) {
case RUN:
// Do all the batch drawing here
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
elipsedTime += Gdx.graphics.getDeltaTime();
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(backgroundSprit, 0, 0, w, h);
batch.draw(bucketSprite, bucketSpriteRect.x, bucketSpriteRect.y,
bucketSprite.getWidth() - 160, bucketSprite.getHeight() - 140);
for(Rectangle fireball: fireballArray) {
batch.draw(fireballSprite, fireball.x, fireball.y,
fireballSprite.getWidth() - 20, fireballSprite.getHeight() - 20);
}
batch.draw(progressBarSkin.getSprite("progressBarBg"), 200, flipCoordinates(h, 170));
batch.draw(progressBarSkin.getSprite("progressBar"),
210, flipCoordinates(h, 162), barLength, 6); // <---- modify x, x, <x>, x to adjust the length of the life-bar
batch.draw(heartSprite, 95, flipCoordinates(h, 200), 90, 76);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
batch.end();
/***************************************Debugging Rectangles************************************/
// Draw rects around sprites
// bucketRenderer.begin(ShapeRenderer.ShapeType.Line);
// bucketRenderer.setColor(Color.GREEN);
// bucketRenderer.rect(bucketSpriteRect.getX(), bucketSpriteRect.getY(),
// bucketSprite.getWidth() - 160, bucketSprite.getHeight() -140);
// bucketRenderer.end();
//
// bucketRenderer.begin(ShapeRenderer.ShapeType.Line);
// bucketRenderer.setColor(Color.RED);
// bucketRenderer.rect(bucketRect.getX(), bucketRect.getY(), 100, 10);
// //bucketRenderer.point(bucketRect.getX(), bucketRect.getY(), 0f);
// bucketRenderer.end();
//
// fireballRenderer.begin(ShapeRenderer.ShapeType.Line);
// fireballRenderer.setColor(Color.WHITE);
// fireballRenderer.rect(fireBallRect.x, fireBallRect.y,
// fireballSprite.getWidth() - 20, fireballSprite.getHeight() - 20);
// fireballRenderer.end();
// To avoid sprite flickering, surround batch.draw with a game state check
if (state != State.PAUSE) {
Iterator<Rectangle> iter = fireballArray.iterator();
while(iter.hasNext()) {
fireBallRect = iter.next();
fireBallRect.y -= fireballSpeed * Gdx.graphics.getDeltaTime();
// Remove the fireBallRect from the array as soon as it leaves the screen
if(fireBallRect.y + 106 < 0) {
iter.remove();
// The player missed the fireball, play a the fireball_missed_sound
fireball_missed_sound.play();
// Subtract a ball from the total number allowed to be missed
numOfBallsLeft --;
// Call life deduction
deductLifePoints();
// Check to see if this is the last fball left to fail
if (numOfBallsLeft == 1) {
}
// Check to see if life points are 0 or < 0
if (numOfBallsLeft <= 0) {
// Game over logic
barLength = 0;
// Set the game state to PAUSED
//state = State.PAUSE;
//bucketSprite.setColor(Color.RED);
batch.begin();
batch.draw(bucketSprite, bucketSpriteRect.x, bucketSpriteRect.y,
bucketSprite.getWidth() - 160, bucketSprite.getHeight() - 140);
batch.end();
}
}
// Collision detector
if(bucketRect.overlaps(fireBallRect)) {
catchFireball.play(volume);
// Start and draw animagion of fireball catch
batch.begin();
batch.draw(catch_animation.getKeyFrame(elapsedTime, true), fireBallRect.getX(), fireBallRect.getY());
batch.end();
// Remove the fireball that collides with the bucket
iter.remove();
}
}
}
// Touch input controller
if(Gdx.input.isTouched()) {
Vector3 touchPos = new Vector3();
touchPos.set(Gdx.input.getX(), Gdx.input.getY(), 0);
camera.unproject(touchPos);
if(touchPos.y <= 250) {
bucketSpriteRect.setX(touchPos.x - 115);
bucketRect.setX(touchPos.x - 50); // <---- adjust position left/right on touch
}
}
if(TimeUtils.nanoTime() - lastFireballTime > fireballFrequency) {
fireBallRect = new Rectangle();
fireBallRect.x = MathUtils.random(50, w - 270);
fireBallRect.y = h;
fireBallRect.width = 75;
fireBallRect.height = 75;
fireballArray.add(fireBallRect);
lastFireballTime = TimeUtils.nanoTime();
}
/**************************************************************************************************/
break;
case PAUSE:
// Pause the game here
/******************************** Redraw the sprites to avoid flickering **************************/
batch.begin();
batch.draw(backgroundSprit, 0, 0, w, h);
batch.draw(bucketSprite, bucketSpriteRect.x, bucketSpriteRect.y,
bucketSprite.getWidth() - 160, bucketSprite.getHeight() - 140);
for(Rectangle fireball: fireballArray) {
batch.draw(fireballSprite, fireball.x, fireball.y,
fireballSprite.getWidth() - 20, fireballSprite.getHeight() - 20);
}
batch.draw(progressBarSkin.getSprite("progressBarBg"), 200, flipCoordinates(h, 170));
batch.draw(progressBarSkin.getSprite("progressBar"),
210, flipCoordinates(h, 162), barLength, 6); // <---- modify x, x, <x>, x to adjust the length of the life-bar
batch.draw(heartSprite, 95, flipCoordinates(h, 200), 90, 76);
//pauseButton.draw(batch, 1);
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
batch.end();
/**************************************************************************************************/
break;
case RESUME:
break;
default:
break;
}
}
/************************************* Implement Dispose **************************************/
#Override
public void dispose() {
batch.dispose();
bucketRenderer.dispose();
fireballRenderer.dispose();
backgroundImage.dispose();
bucketImage.dispose();
fireballImage.dispose();
bucket_tap.dispose();
bucket_drag.dispose();
catchFireball.dispose();
bgMusic.dispose();
fireball_missed_sound.dispose();
progressBarSkin.dispose();
fballAtlas.dispose();
stage.dispose();
}
/************************************* Flip Coordinates Method ********************************/
public static float flipCoordinates(float height, float xORy) {
float newPosition = height - xORy;
return newPosition;
}
/************************************** Deduces Life Points ***********************************/
private void deductLifePoints() {
barLength -= deductedBarSegment;
}
/************************************** Set the Game's state **********************************/
public void setGameState(State s) {
this.state = s;
}
/******************************** Android's Lyfe-Cycle Overrides ******************************/
#Override
public void pause() {
super.pause();
this.state = State.PAUSE;
}
#Override
public void resume() {
super.resume();
this.state = State.PAUSE;
}
}
The first parameter of the Animation constructor is the frameDuration in seconds. You are passing it 1/15f, which is really fast. Try something greater, like 0.15f.