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
Related
I am trying to move actor on stage from point to point by actions and it is not working, i have tried for hours and it just not working, i will be glad for help..
I have searched by the internet for codes and all i tried didn't worked, i really dont understand what is wrong with this code, it is basically the same as a working one on a tutorial in the internet
the actor class:
public class Player extends Actor {
float x,y;
float screenWidth,screenHeight;
private Sprite sprite;
Texture image;
float width,height;
public Player(Texture image,float x, float y,float width,float height, float screenWidth, float screenHeight)
{
this.width = width;
this.height = height;
this.x = x;
this.y = y;
this.screenWidth = screenWidth;
this.screenHeight = screenHeight;
this.image = image;
sprite = new Sprite(image, 0, 0, image.getWidth(), image.getHeight());
sprite.setPosition(x, y);
}
#Override
public float getX() {
return x;
}
#Override
public void setX(float x) {
this.x = x;
}
#Override
public float getY() {
return y;
}
#Override
public void setY(float y) {
this.y = y;
}
#Override
public float getWidth() {
return width;
}
#Override
public void setWidth(float width) {
this.width = width;
}
#Override
public float getHeight() {
return height;
}
#Override
public void setHeight(float height) {
this.height = height;
}
#Override
public void act(float delta) {
super.act(delta);
}
#Override
public void draw (Batch batch, float parentAlpha) {
batch.draw(sprite,x,y,width,height);
}
}
and the main class:
player = new Player(playerTexture,screenWidth/2,screenHeight-200,playerTexture.getWidth(),playerTexture.getHeight(),screenWidth,screenHeight);
MoveToAction action = new MoveToAction();
action.setPosition(300f,0f);
action.setDuration(10f);
player.addAction(action);
#Override
public void render(float delta) {
Gdx.gl.glClearColor(1, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(orthographicCamera.combined);
batch.begin();
// batch.draw(playerTexture,10,10,10,10);
batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw(); //this will call the batch to draw the sprite
}
Actor already has x, y, width, and height fields. Since you created your own, you have hidden those parameters.
The source of your problem is that you failed to override setPosition() to use your fields. So the move action calls that and changes the fields that you have hidden and when you draw it, you are using your own fields that have not been changed.
Don't hide fields. It is very error-prone. You should delete the fields I mentioned above, along with all your overrides of getters and setters.
Here's a rule of thumb for OOP in general: if you are overriding any getter or setter without calling the super method, you are probably breaking something.
Unrelated, but you should be using TextureRegion instead of Sprite. A Sprite is a TextureRegion with additional parameters for size and position. Since those features are also in Actor, it is redundant and error-prone to use Sprite.
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);
}
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.
I have the following class:
public class AnimationDemo implements ApplicationListener {
private SpriteBatch batch;
private TextureAtlas textureAtlas;
private Animation animation;
private float elapsedTime = 0;
private OrthographicCamera camera;
private int width;
private int height;
private int texturewidth;
private int textureheight;
#Override
public void create() {
width = Gdx.graphics.getWidth();
height = Gdx.graphics.getHeight();
camera = new OrthographicCamera(width, height);
camera.position.set(width / 2, height / 2, 0);
camera.update();
batch = new SpriteBatch();
textureAtlas = new TextureAtlas(Gdx.files.internal("data/packone.atlas"));
textureAtlas.getRegions().sort(new Comparator<TextureAtlas.AtlasRegion>() {
#Override
public int compare(TextureAtlas.AtlasRegion o1, TextureAtlas.AtlasRegion o2) {
return Integer.parseInt(o1.name) > Integer.parseInt(o2.name) ? 1 : -1;
}
});
animation = new Animation(1 / 15f, textureAtlas.getRegions());
}
#Override
public void dispose() {
batch.dispose();
textureAtlas.dispose();
}
#Override
public void render() {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT);
batch.begin();
elapsedTime += Gdx.graphics.getDeltaTime();
batch.draw(animation.getKeyFrame(elapsedTime, true), 0, 0);
batch.end();
}
#Override
public void resize(int width, int height) {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
}
In the above I am using the Animation class to simply draw from a texture atlas. I am following an example from another SO question which is here but the co-ordinates don't fit my equation. How should I set these:
private int texturewidth;
private int textureheight;
Any help would be great :)
you need to care about proper offset - the origin is always at the left bottom corner and that is why you need to subtract half of width and height when drawing.
In a nutshell it should be like:
TextureRegion region = animation.getKeyFrame(elapsedTime, true);
batch.draw(region, 0 - (region.getRegionWidth()/2f), 0 - (region.getRegionHeight()/2f));
I defined new actor this way:
class MyActor extends Image
{
Texture texMyActor;
public MyActor()
{
super.setTouchable(Touchable.enabled);
texMyActor = new Texture("data/myActor.png");
addListener(new InputListener()
{
public boolean touchDown(InputEvent event, float x, float y,
int pointer, int button)
{
System.out.println("down");
return true;
}
public void touchUp(InputEvent event, float x, float y,
int pointer, int button)
{
System.out.println("up");
}
});
}
#Override
public void act(float delta)
{
super.act(delta);
}
#Override
public void draw(SpriteBatch batch, float parentAlpha)
{
batch.draw(texMyActor, 200, 200);
}
}
I also added actor to stage, registered stage as current input processor.
Then I call stage.act(deltaTime) and stage.draw().
I see my actor but it doesn't respont to input
What's wrong with my code? :?:
You have to setBounds of your actor as well
add to your constructor :
texMyActor = new Texture("data/myActor.png");
//setting width and height according to the texture
setWidth(texMyActor.getWidth());
setHeight(texMyActor.getHeight());
//setting bound of the actor
setBounds(200, 200, getWidth(), getHeight());
notice i set the bounds position to 200 , 200 since you draw there