I am trying to draw different textures of balloons and I want them to appear in different times about half second between each one, and move in the world. first balloons are rendered but after about half second the other balloons are rendered next to the previous ones, not in the initial place:
this is code:
private Ballons ballons;
private Ballons ballons2;
private Ballons ballons3;
private Ballons ballons4;
private Texture background;
public Celebration(Fruits game, float level)
{
this.game=game;
this.level=level;
gamecam=new OrthographicCamera();
gameport=new StretchViewport(820/Fruits.PPM,580/Fruits.PPM,gamecam);
stage=new Stage(gameport,((Fruits) game).batch);
background=new Texture("Wining.jpg");
gamecam.position.set(gameport.getWorldWidth()/2f,gameport.getWorldHeight()/2f,0);
temp=0;
counter=400;
world=new World(new Vector2(0,0.5f),true);
b2dr=new Box2DDebugRenderer();
ballons=new Ballons(world,this,1,140);
ballons4=new Ballons(world,this,2,290);
ballons3=new Ballons(world,this,3,480);
ballons2=new Ballons(world,this,4,650);
}
#Override
public void show() {
}
public void handleinput(float dt)
{
if(Gdx.input.isTouched())
game.setScreen(new GlobalWorld(game, 1));
}
public void update(float dt)
{
handleinput(dt);
world.step(1 /60f, 6, 2);
//player.update(dt);
gamecam.update();
// renderer.setView(gamecam);
ballons.update(dt);
ballons2.update(dt);
ballons3.update(dt);
ballons4.update(dt);
}
#Override
public void render(float delta) {
float level;
update(delta);
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
counter--;
b2dr.render(world, gamecam.combined);
game.batch.setProjectionMatrix(gamecam.combined);
game.batch.begin();
game.batch.draw(background, 0, 0, gameport.getWorldWidth(), gameport.getWorldHeight());
if (counter < 200) {
ballons.draw(game.batch);
ballons2.draw(game.batch);
}
if (counter < 100) {
ballons3.draw(game.batch);
ballons4.draw(game.batch);
}
game.batch.end();
}
#Override
public void resize(int width, int height) {
gameport.update(width, height);
}
}
Ballons class:
public class Ballons extends Sprite {
public World world;
public Body b2body;
private TextureRegion collectorStand;
public Ballons(World world,Celebration screen,float image, float x)
{
// super(screen.getAtlas().findRegion("boy1"));
this.world=world;
defineCollector(x);
if(image==1) {
collectorStand = new TextureRegion(new Texture("Balloon1.png"));
setBounds(0, 0, 200 / Fruits.PPM, 200 / Fruits.PPM);
}
else if(image==2) {
collectorStand = new TextureRegion(new Texture("Balloon2.png"));
setBounds(0, 0, 170 / Fruits.PPM, 185 / Fruits.PPM);
}
else if(image==3) {
collectorStand = new TextureRegion(new Texture("Balloon3.png"));
setBounds(0, 0, 150 / Fruits.PPM, 175 / Fruits.PPM);
}
else if(image==4) {
collectorStand = new TextureRegion(new Texture("Balloon4.png"));
setBounds(0, 0, 150 / Fruits.PPM, 175 / Fruits.PPM);
}
else if(image==5) {
collectorStand = new TextureRegion(new Texture("Balloon5.png"));
setBounds(0, 0, 150 / Fruits.PPM, 175 / Fruits.PPM);
}
setRegion(collectorStand);
}
public void update(float dt)
{
setPosition(b2body.getPosition().x-getWidth()/2,b2body.getPosition().y-getHeight()/2.8f);
}
public void defineCollector(float x)
{
BodyDef bdef=new BodyDef();
bdef.position.set(x/Fruits.PPM,-20/Fruits.PPM);
bdef.type=BodyDef.BodyType.DynamicBody;
b2body=world.createBody(bdef);
FixtureDef fdef=new FixtureDef();
CircleShape shape=new CircleShape();
shape.setRadius(15/Fruits.PPM);
fdef.shape=shape;
b2body.createFixture(fdef);
}
}
No matter what actual counter value is you are calling update(delta); inside your render method. I see there
ballons.update(dt);
ballons2.update(dt);
ballons3.update(dt);
ballons4.update(dt);
Unfortunately you have not attached Ballons class implementation but I'm pretty sure that update method is modifying balloons'es positions.
You should call then ballon's update method inside your if-else statements rather not inside the update method. It could look like
public void update(float dt)
{
handleinput(dt);
world.step(1 /60f, 6, 2);
//player.update(dt);
gamecam.update();
//renderer.setView(gamecam);
}
#Override
public void render(float delta) {
...
if (counter < 200) {
ballons.update(dt);
ballons2.update(dt);
ballons.draw(game.batch);
ballons2.draw(game.batch);
}
if (counter < 100) {
ballons3.update(dt);
ballons4.update(dt);
ballons3.draw(game.batch);
ballons4.draw(game.batch);
}
The problem is that your update function is only fixing the position of the balloons to the Box2D body. Since the Box2D body is created and added to the world on creation, the body will still be moving even though it is not drawn.
You can disable the balloon's bodies until they are ready to be drawn, like so:
Balloons.java
public void defineCollector(float x) {
BodyDef bdef=new BodyDef();
bdef.position.set(x/Fruits.PPM,-20/Fruits.PPM);
bdef.type=BodyDef.BodyType.DynamicBody;
b2body=world.createBody(bdef);
FixtureDef fdef=new FixtureDef();
CircleShape shape=new CircleShape();
shape.setRadius(15/Fruits.PPM);
fdef.shape=shape;
b2body.createFixture(fdef);
b2body.setActive(false);
}
Celebration.java
public Celebration(Fruits game, float level) {
...
stage.addAction(
Actions.sequence(
Actions.delay(0.5f),
Actions.run(
new Runnable() {
ballons.b2body.setActive(true);
ballons2.b2body.setActive(true);
}
),
Actions.delay(0.5f),
Actions.run(
new Runnable() {
ballons3.b2body.setActive(true);
ballons4.b2body.setActive(true);
}
)
)
);
}
public void update(float dt) {
stage.act(dt);
...
}
#Override
public void render(float delta) {
...
if (ballons.b2body.isActive()) {
ballons.draw(game.batch);
}
if (ballons2.b2body.isActive()) {
ballons2.draw(game.batch);
}
if (ballons3.b2body.isActive()) {
ballons3.draw(game.batch);
}
if (ballons4.b2body.isActive()) {
ballons4.draw(game.batch);
}
}
I would recommend using Scene2D to handle your logic by changing your balloons to extend Image and adding your balloons to the stage like so: stage.addActor(balloon). You can then handle your logic inside of the act method, and override draw to position the texture over the Box2D body.
Related
This is my first try in libGDX and I've not seen an issue like this before, googling didn't help either. What I'm trying to to display a background, Later on I'll make this move, but for me it was a great start to actually display the image. It displays, but it's streched out (See picture below)
And my code is:
private BombArrangement game;
private OrthographicCamera gameCamera;
private Viewport gamePort;
private Texture backGroundTexture;
public PlayScreen(BombArrangement game) {
this.game = game;
gameCamera = new OrthographicCamera();
gamePort = new FitViewport(BombArrangement.V_WIDTH, BombArrangement.V_HEIGHT, gameCamera);
backGroundTexture = new Texture("startbackground.png");
}
#Override
public void show() {
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
game.batch.begin();
game.batch.draw(new TextureRegion(backGroundTexture, 0, 0, BombArrangement.V_WIDTH, BombArrangement.V_HEIGHT), 0, 0);
game.batch.end();
}
#Override
public void resize(int width, int height) {
gamePort.update(width, height);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
}
}
I tried several things like textureregions, sprites and more but all of them give this result.
not exactly sure what your want to do but i use this to render my background in my main menu:
//Camera
camera = new OrthographicCamera();
camera.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
//Viewport
ScreenViewport viewport = new ScreenViewport(camera);
//Background
backgroundImage = new Texture(pathToImage);
//Stage
stage = new Stage();
stage.setViewport(viewport);
(this is located in my constructor and camera, backgroundImage and stage are fields in my class)
in render method
(ConfigData holds data of settings applied to the game; DEFAULT_WIDHT and -HEIGHT are just some values I use to initialize the window when not in fullscreen mode; Replace them with your values used in the DesktopLauncher for
config.widht
and
config.height
):
#Override
public void render(float delta) {
//Clear screen
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act();
stage.getBatch().begin();
stage.getBatch().draw(backgroundImage, 0, 0, ConfigData.DEFAULT_WIDTH, ConfigData.DEFAULT_HEIGHT);
stage.getBatch().end();
stage.draw();
}
my resize method:
#Override
public void resize(int width, int height) {
camera.setToOrtho(false, width, height);
stage.getViewport().update(width, height);
}
hopes this helps somehow someone because i figured out this by myself and it costed some effort (:
As a response to your last comment:
You are now scaling down the height correctly but the width remains the same. Try to multiply the width by the same amount you scale the height down, so with some alterations to the code you linked in the comment (not tested):
private Texture texture;
private int x1, x2, speed, scaledHeight, scaledWidth;
public StartBackground() {
texture = new Texture("startbackground.png");
x1 = 0;
x2 = texture.getWidth();
speed = 5;
float imageRatio = Gdx.graphics.getHeight() / texture.getHeight();
scaledHeight = (int) (texture.getHeight() * imageRatio);
scaledWidth = (int) (texture.getWidth() * imageRatio);
}
public void updateAndRender(float deltaTime, SpriteBatch spriteBatch) {
x1 -= speed;
x2 -= speed;
// If image is off screen and not visible
if (x1 + texture.getWidth() <= 0) x1 = x2 + texture.getWidth();
if (x2 + texture.getWidth() <= 0) x2 = x1 + texture.getWidth();
// Render
spriteBatch.draw(texture, x1, 0, scaledWidth, scaledHeight);
spriteBatch.draw(texture, x2, 0, scaledWidth, scaledHeight);
}
First, thank you for reading this post, any help is welcome.
My actor is correctly rendered on the stage, but with the Actions.moveTo, it leaves a trail ? I just don't get it. It's like the texture is rendered at a new position on every new frame.
Here is my code for my class :
public class SlidingCap extends Actor {
private Texture capOver;
private float xPosition;
private float yPosition;
public SlidingCap(float x, float y) {
this.xPosition = x;
this.yPosition = y;
this.capOver = new Texture(Gdx.files.internal("images/cappingPlate.png"));
setBounds(x, y, 288, 180);
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(capOver, getX(), getY(), 288, 180);
this.addAction(Actions.moveTo(xPosition+10, yPosition+10, 5f));
}
}
And the ScreenGame render method:
#Override
public void render(float delta) {
gameStage.act(delta);
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
this.capMiniGame = new SlidingCap(100, 100);
this.gameStage.addActor(capMiniGame);
gameStage.draw();
}
You're adding a new SlidingCap every frame with this code
this.capMiniGame = new SlidingCap(100, 100);
this.gameStage.addActor(capMiniGame);
Try adding the SlidingCap once in the Create or show method instead of every frame
So I have this simple pong game but I'm trying to change it up a bit, the thing is I'm currently struggling with having to duplicate or create various balls in the game for it to work the way I want to. I'm uncertain if I should use an arraylist and if so how should I do it? any suggestions would really be appreciated.
public class ColorPong implements ApplicationListener {
private Rectangle field = new Rectangle();
private Ball ball = new Ball();
private float fieldTop, fieldBottom, fieldLeft, fieldRight;
#Override
public void create() {
field.set(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
fieldLeft = field.x;
fieldRight = field.x + field.width;
fieldBottom = field.y;
fieldTop = field.y + field.height;
ball.BallCreation();
reset();
}
#Override
public void resize(int width, int height) {
}
#Override
public void render() {
float dt = Gdx.graphics.getRawDeltaTime();
update(dt);
draw(dt);
}
private void draw(float dt) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
ball.DrawingBall(dt);
}
private void update(float dt) {
updateBall(dt);
}
private void updateBall(float dt) {
ball.Intergrate(dt);
ball.updateBounds();
//------------------
if(ball.Left() < fieldLeft){
ball.move(fieldLeft, ball.getY());
ball.Reflect(true, false);
}
if(ball.Right() > fieldRight){
ball.move(fieldRight - ball.getWidth(), ball.getY());
ball.Reflect(true, false);
}
if(ball.Bottom() < fieldBottom){
ball.move(ball.getX(), fieldBottom);
ball.Reflect(false, true);
}
if(ball.Top() > fieldTop){
ball.move(ball.getX(), fieldTop - ball.getHeight());
ball.Reflect(false, true);
}
}
public void reset(){
ball.move(field.x + (field.width - ball.getWidth()) / 2, (field.y + field.height) / 2);
Vector2 velocity = ball.getVelocity();
velocity.set(300, 150);
velocity.setAngle(360f - 45f);
ball.setVelocity(velocity);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
}
}
and here is the Ball class
private ShapeRenderer ballRenderer;
private Color ballColor = new Color();
public Ball() {
super(32, 32);
}
public void Reflect(boolean x, boolean y){
Vector2 velocity = getVelocity();
if(x) velocity.x *= -1;
if(y) velocity.y *= -1;
setVelocity(velocity);
}
public void BallCreation(){
ballRenderer = new ShapeRenderer();
}
public void DrawingBall(float dt){
ballRenderer.begin(ShapeType.Filled);
drawBall(dt);
ballColorSwap();
ballRenderer.end();
}
int THRESHOLD = 900; // 4 seconds
long lastChanged = 0; // timestamp
public void ballColorSwap(){
// maybe call it here?
if(System.currentTimeMillis() - lastChanged < THRESHOLD)
return;
int rnd = (int)(Math.random() * 4);
switch(rnd){
case 0: ballColor.set(Color.GREEN);break;
case 1: ballColor.set(Color.BLUE);break;
case 2: ballColor.set(Color.RED);break;
case 3: ballColor.set(Color.YELLOW);break;
}
lastChanged = System.currentTimeMillis();
}
private void drawBall(float dt) {
ballRenderer.circle(this.getX(), this.getY(), 20);
ballRenderer.setColor(ballColor);
}
}
In Java, whenever I want to keep track of an arbitrary number of objects I typically use an ArrayList; they are quite handy once you learn how to use them effectively.
Here's an example of how you might use an ArrayList with your update and updateBall methods:
//initialize in create()
ArrayList<Ball> balls;
private void update(float dt) {
//Pretty much saying 'For every ball in Balls, assign it to 'b' and do something with it
for(Ball b : balls) {
updateBall(b, dt);
}
}
private void updateBall(Ball b, float dt) {
b.Intergrate(dt);
b.updateBounds();
//------------------
if(b.Left() < fieldLeft){
b.move(fieldLeft, ball.getY());
b.Reflect(true, false);
}
if(b.Right() > fieldRight){
b.move(fieldRight - b.getWidth(), b.getY());
b.Reflect(true, false);
}
if(b.Bottom() < fieldBottom){
b.move(b.getX(), fieldBottom);
b.Reflect(false, true);
}
if(b.Top() > fieldTop){
b.move(b.getX(), fieldTop - b.getHeight());
b.Reflect(false, true);
}
}
And of course to draw the ball, just do the for(Ball.... thing again and call b.DrawingBall()
This question has been posted before, but i have problems with flickering sprites in libGdx.
I have looked everywhere on stackoverflow, google, etc but nothing helped me.
The sprites only flicker when they move. It flickers less when i move them slower, but it flickers a lot when a little bit faster. This is very annoying and ofcourse unplayable.
This is my code:
package com.wouter.DuelArena;
import com.badlogic.gdx.Game;
import ...
public class DuelArena extends Game {
Sprite player;
float playerX;
float playerY;
boolean fireBool;
Sprite fireSprite;
Texture fireText;
OrthographicCamera cam;
Texture playerTexture;
SpriteBatch batch;
#Override
public void create() {
fireBool = false;
fireText = new Texture("data/droplet.png");
fireText.setFilter(TextureFilter.Linear, TextureFilter.Linear);
fireSprite = new Sprite(fireText);
playerTexture = new Texture("data/bucket.png");
playerTexture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
player = new Sprite(playerTexture);
player.setSize(70, 128);
playerX = 0f;
playerY = 0f;
cam = new OrthographicCamera();
cam.setToOrtho(false, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
batch = new SpriteBatch();
}
#Override
public void dispose() {
super.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(Gdx.gl10.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
player.draw(batch);
input();
update();
batch.end();
super.render();
}
private void update()
{
player.setPosition(playerX, playerY);
if (fireBool)
{
fireSprite.setX(fireSprite.getX() + 300 * Gdx.graphics.getDeltaTime());
fireSprite.draw(batch);
if (fireSprite.getX() > 1280)
fireBool = false;
}
}
private void input()
{
if (Gdx.input.isKeyPressed(Keys.LEFT) && player.getX() > 0)
{
playerX -= 200f * Gdx.graphics.getDeltaTime();
}
if (Gdx.input.isKeyPressed(Keys.RIGHT) && player.getX() < 1280)
{
playerX += 200f * Gdx.graphics.getDeltaTime();
}
if (Gdx.input.isKeyPressed(Keys.SPACE) && !fireBool)
{
fireBool = true;
fireSprite.setPosition(playerX, playerY + 35f * Gdx.graphics.getDeltaTime());
}
}
#Override
public void resize(int width, int height) {
super.resize(width, height);
}
#Override
public void pause() {
super.pause();
}
#Override
public void resume() {
super.resume();
}
}
Thanks beforehand!
The problem is the position of the call to the super.render:
super.render();
In a Game class, the super.render needs to be the first line in the code, not the last, like this:
#Override
public void render(){
super.render(); //<-----
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(Gdx.gl10.GL_COLOR_BUFFER_BIT);
cam.update();
batch.setProjectionMatrix(cam.combined);
batch.begin();
player.draw(batch);
input();
update();
batch.end();
}
It is actually very important to put it there if you override the render method in Game, because thats the one that calls the render of the current Screen. You aren't using Screens in this example, but if you are using Game you probably should (will :p).
I'm new to libgdx, I'm trying to make a sprite move while the camera follows. I can make the sprite move perfectly until I attach the camera to it. When I click, the sprite will move wherever it feels like (it seems) and the camera will follow properly. I've tried a few different things but at this point its just guessing and checking.
public class MyGdxGame implements ApplicationListener {
OrthographicCamera mCamera;
SpriteBatch mBatch;
Texture mTexture, mMap;
Sprite sprite;
float touchX, touchY;
float spriteX, spriteY, speed = 5;
#Override
public void create() {
float CAMERA_WIDTH = 480, CAMERA_HEIGHT = 320;
mBatch = new SpriteBatch();
mTexture = new Texture(Gdx.files.internal("data/logo.png"));
mMap = new Texture(Gdx.files.internal("data/sc_map.png"));
mCamera = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);
mCamera.setToOrtho(false, CAMERA_WIDTH, CAMERA_HEIGHT);
}
#Override
public void dispose() {
}
#Override
public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
mBatch.setProjectionMatrix(mCamera.combined);
mCamera.update();
mBatch.begin();
updateInput();
drawD();
mBatch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
public void drawD() {
mCamera.position.set(spriteX, spriteY, 0);
mBatch.draw(mMap, 0, 0);
mBatch.draw(mTexture, spriteX, spriteY);
}
public void updateInput() {
if (Gdx.input.justTouched()) {
touchX = Gdx.input.getX();
touchY = Gdx.input.getY();
}
if (touchX != spriteX) {
if (spriteX < touchX) {
spriteX += speed;
}
if (spriteX > touchX) {
spriteX -= speed;
}
}
if (touchY != spriteY) {
if (spriteY > Gdx.graphics.getHeight() - touchY) {
spriteY -= 10;
}
if (spriteY < Gdx.graphics.getHeight() - touchY) {
spriteY += 10;
}
}
}
}
Since you have spent a decent amount of time and are trying to get it working, I will give you a little push forward closer to what you are looking for. Look over the changes I made and below I will outline what I did to help you understand the code better.
Orthographic Camera, when you setup the camera 0,0 is the center of the screen. The width and the height are what you specified into the constructor. So the top edge would be x, 160 and the bottom edge would be x, -160. The left edge would be -240, y and the right edge would be 240, y.
drawD() Notice that I'm drawing the sprite in the middle of the image and it isn't moving. I instead move the map around in the opposite direction (y is inverted).
updateInput() Notice I pass in a delta value (this is the time in seconds between frames) this allows you to smoothly move things. The speed is 120, so this will smoothly move your character at a rate of 120/second.
The if condition is basically a simply way to compare the float values so it stops when it gets close enough. This prevents it from over shooting the target position and then bouncing back and forth because it might not be able to get to the exact value.
I added dispose calls for the textures you loaded, these are important as you don't want to fill up your memory.
I hope this helps get you started and pointed in the right direction. Working on games is a lot of work and takes time, so be patient and be ready to learn lots along the way!
Based on your comment I believe what you are looking for is something closer to this:
public class MyGdxGame implements ApplicationListener {
OrthographicCamera mCamera;
SpriteBatch mBatch;
Texture mTexture, mMap;
float touchX, touchY;
float spriteX, spriteY, speed = 120;
final float CAMERA_WIDTH = 480, CAMERA_HEIGHT = 320;
#Override public void create() {
mCamera = new OrthographicCamera(CAMERA_WIDTH, CAMERA_HEIGHT);
mBatch = new SpriteBatch();
mTexture = new Texture(Gdx.files.internal("data/logo.png"));
mMap = new Texture(Gdx.files.internal("data/sc_map.png"));
}
#Override public void dispose() {
mTexture.dispose();
mMap.dispose();
}
#Override public void render() {
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
updateInput(Gdx.graphics.getDeltaTime());
mCamera.update();
mBatch.setProjectionMatrix(mCamera.combined);
mBatch.begin();
drawD();
mBatch.end();
}
#Override public void resize(final int width, final int height) {}
#Override public void pause() {}
#Override public void resume() {}
public void drawD() {
mBatch.draw(mMap, -spriteX - (mMap.getWidth() / 2), spriteY - (mMap.getHeight() / 2));
mBatch.draw(mTexture, -32, -32, 64, 64);
}
public void updateInput(final float delta) {
if (Gdx.input.justTouched()) {
touchX = Gdx.input.getX() - (Gdx.graphics.getWidth() / 2);
touchY = Gdx.input.getY() - (Gdx.graphics.getHeight() / 2);
}
final float dv = delta * speed;
if (Math.abs(touchX - spriteX) > 1) {
if (spriteX < touchX) {
spriteX += dv;
}
if (spriteX > touchX) {
spriteX -= dv;
}
}
if (Math.abs(touchY - spriteY) > 1) {
if (spriteY > touchY) {
spriteY -= dv;
}
if (spriteY < touchY) {
spriteY += dv;
}
}
}
}