I have a stack which I'm filling with tables . I'm trying to fadeIn, fadeOut, moveTo, several of these actors but the addAction methods don't work:
stack_stage = new Stack();
table_menu = new Table();
level_selector = new ex01MenuLevelSelectorBase(skin, table_menu);
table_menu.add(level_selector).center();
table_menu.setFillParent(true);
stack_stage.setFillParent(true);
stack_stage.add(table_menu);
stage.addActor(stack_stage);
table_level_selector = new Table();
image_level_selector = new Image(skin.getDrawable("hud-level5"));
image_level_selector.setColor(1f, 1f, 1f, 0.5f);
table_level_selector.add(image_level_selector);
stack_stage.addActor(table_level_selector);
//doesn't work
table_level_selector.addAction(com.badlogic.gdx.scenes.scene2d.actions.Actions.fadeOut(5f));
//works
table_level_selector.addAction(com.badlogic.gdx.scenes.scene2d.actions.Actions.hide());
try this
table_level_selector.addAction(Actions.sequence(Actions.fadeOut(5f),Actions.hide ()));
or
table_level_selector.addAction(Actions.sequence(
com.badlogic.gdx.scenes.scene2d.actions.Actions.fadeOut(5f),
com.badlogic.gdx.scenes.scene2d.actions.Actions.hide ()));
is likely that this is your mistake, try this in the render method
stage.act(Gdx.graphics.getDeltaTime());
I know it's a bit late, but today I encountered the same and problem and realized that I hadn't added
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
in the render method. This caused my image to draw over itself:
When it faded in it took less than I expected (because the alphas were adding)
When it faded out the image didn't change (because there was the same image underneath)
I know this isn't your case, but this error took me some time to figure out what wasn't working just to discover this little oversight!
Related
The title pretty much say it all, I need to get a image from a Model is this posible? I searched for this and found nothing.
Solution thanks to #retodaredevil
FrameBuffer fbo = new FrameBuffer(Pixmap.Format.RGBA4444, screenWidth, screenHeight, true);
ModelBatch batch = new ModelBatch();
fbo.begin(); // make fbo the current buffer
Gdx.gl.glViewport(0, 0,screenWidth, screenHeight);
Gdx.gl.glClear(GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
batch.begin(camera);
batch.render(instance, environment);
batch.end();
try{
FileHandle fh = new FileHandle(output);
Pixmap pixmap = ScreenUtils.getFrameBufferPixmap(0,0,screenWidth,screenHeight);
PixmapIO.writePNG(fh, pixmap);
pixmap.dispose();
}catch (Exception e){
e.printStackTrace();
}
fbo.end(); // Now you can draw on the display again
batch.dispose();
fbo.dispose();
From what I understand, we'll have to use two different tutorials
https://github.com/mattdesl/lwjgl-basics/wiki/FrameBufferObjects
https://xoppa.github.io/blog/basic-3d-using-libgdx/ (You're probably already familiar with this)
FrameBuffer fbo = new FrameBuffer(Pixmap.Format.RGBA4444, width, height, hasDepth);
// I've never used a FrameBuffer before so you may have to play around with constructor parameters
ModelBatch batch = // your ModelBatch initialization here
fbo.begin(); // make fbo the current buffer
glClearColor(0f, 0f, 0f, 1f);
glClear(GL_COLOR_BUFFER_BIT);
batch.resize(fbo.getWidth(), fbo.getHeight());
batch.begin();
batch.render(modelInstance, environment);
batch.end();
fbo.end(); // Now you can draw on the display again
// If you want to, you can resize your batch and use it to draw on the display
batch.resize(Display.getWidth(), Display.getHeight());
Once you do whatever you need to do to your FrameBuffer, you can get the texture
fbo.getTexture();
EDIT: That method doesn't exist, look at OP's question for solution
EDIT 2: FrameBuffer does actually have a method called getColorBufferTexture()
For saving a texture, look at https://www.badlogicgames.com/forum/viewtopic.php?p=8358#p8358 or https://www.badlogicgames.com/forum/viewtopic.php?t=5686
I used this to get one of the links: Libgdx save SpriteBatch in a texture everything else I duckduckgoed
If something doesn't work let me know and I can try to look around more.
I have a com.badlogic.gdx.scenes.scene2d.ui.Image that is built from a Pixmap. The Pixmap is only one pixel because I'm using it to build an Image that functions as a background that can fade in and out.
Pixmap pmap = new Pixmap(1, 1, Pixmap.Format.RGBA8888);
pmap.setColor(1.0f, 1.0f, 1.0f, 1.0f);
pmap.drawPixel(0, 0);
bgImage = new Image(new Texture(pmap));
pmap.dispose();
bgImage.setSize(MyGame.VIRUAL_WIDTH, MyGame.VIRUAL_HEIGHT);
bgImage.getColor().a = 0.0f;
bgImage.addAction(Actions.sequence(Actions.fadeIn(1.0f),Actions.delay(3.0f),Actions.fadeOut(1.0f)));
stage.addActor(bgImage);
It works great but my concern is that the game might be paused while the actions are taking place. I assume the actions will continue upon resuming so I need to keep the same Image but the underlying Pixmap is not managed and therefore needs to be recreated upon resume. I'm having trouble figuring out how to reattach the Texture/Pixmap to the Image. Building the Pixmap itself is easy but getting an existing Image to use it is the problem.
My solution was as follows
Assume Pixmap pixmap = ...
TextureData texData = new PixmapTextureData(pixmap, Format.RGBA8888, false, false, true);
Texture texture = new Texture(texData);
Image image = new Image(texture);
The last flag in PixmapTextureData is "managed". It runs on mine.
You can check out the first portion of the following link to see what is managed and what is not. http://www.badlogicgames.com/wordpress/?p=1513
There is no setTexture method on an Image. Looking at the Image(Texture) constructor it wraps the texture in a drawable region:
this(new TextureRegionDrawable(new TextureRegion(texture)));
So you can do something similar and use the Image.setDrawable method to change the drawable object used. Something like this:
bgImage.setDrawable(new TextureRegionDrawable(new TextureRegion(new Texture(pmap))));
I think you can probably reuse the TextureRegion and all of its containers (so after generating a new pixmap, just wrap it in a Texture and push that into the saved TextureRegion from before the pause.
I am beginning to write a game in LibGDX, only just beginning. I have got a basic tile map loaded, a player sprite and can move the character around and the screen (camera) scrolls around - perfect.
I have two overlayed textures in the bottom right of the screen, a left and right arrow, which are used as the joypad to control the character. I position these in relation to the players.x position, which is always fixed to the centre of the screen. Cool so far .... As below:
/////////////////////////////////////////////////////////////////
private void renderJoypad(float deltaTime)
{
batch.draw(Assets.leftJoypad, blockman.position.x-14, 1, 3, 3);
batch.draw(Assets.rightJoypad, blockman.position.x-9, 1, 3, 3);
}
I am now trying to put the player's score in the top left of the screen. The score is made of a Bitmap font, as below.
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
In my render() method I cam calling some other methods to update, like the positions of the
leftJoypad etc, as in renderJoypad(). I am also calling my draw font method to update the position of the score, however, when I scroll it is all jerky, and sometimes it shows less characters than there should be.
public void drawScore(float deltaTime)
{
font.draw(batch, "00000", blockman.position.x, 10);
}
I believe that I need to place the score (and any other on screen texts, HUD etc) into a stage, but I cannot understand how to get it working with my existing code.
My show method is as follows:
public void show()
{
//load assets class to get images etc
Assets Assets = new Assets();
//start logging Framerate
Gdx.app.log( GameScreen.LOG, "Creating game" );
fpsLogger = new FPSLogger();
//set the stage - bazinga
Gdx.input.setInputProcessor(stage);
//stage.setCamera(camera);
//stage.setViewport(480, 360, false);
batch = new SpriteBatch();
//load the Joypad buttons
loadJoypad();
//background image
loadBackground();
//sounds
jumpSound = Gdx.audio.newSound(Gdx.files.internal("sounds/slime_jump.mp3"));
//LOAD block man here
// load the map, set the unit scale to 1/16 (1 unit == 16 pixels)
loadMap();
//draw the score
font = new BitmapFont(Gdx.files.internal("fonts/minecrafter.fnt"),Gdx.files.internal("fonts/minecrafter.png"),false);
font.setScale(0.02f);
// create an orthographic camera, shows us 30x20 units of the world
camera = new OrthographicCamera();
camera.setToOrtho(false, 30, 20);
camera.update();
// create the Blockman we want to move around the world
blockman = new Blockman();
blockman.position.set(25, 8);
}
and my render() method is as follows:
public void render(float delta)
{
// get the delta time
float deltaTime = Gdx.graphics.getDeltaTime();
stage.act(deltaTime);
stage.draw();
// clear the screen
Gdx.gl.glClearColor(0.3f, 0.3f, 0.3f, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
renderBackground(deltaTime);
batch = renderer.getSpriteBatch();
//updateBlockman(deltaTime);
blockman.update(deltaTime);
// let the camera follow the blockMan, x-axis only
camera.position.x = blockman.position.x;
camera.update();
// set the tile map rendere view based on what the
// camera sees and render the map
renderer.setView(camera);
renderer.render();
//start the main sprite batch
batch.begin();
// render the blockMan
renderBlockman(deltaTime);
renderJoypad(deltaTime);
drawScore(deltaTime);
batch.end();
fpsLogger.log();
}
I have tried to change the way things work with relation to the Spritebatch etc and just cannot seem to get it working as I require.
Can anyone suggest how I may approach getting a stage and actors to work, or a second camera or something to help me achieve a fixed score display in the corner.
Do I need to use Scene 2D or something - aahhh! My head is exploding....
I look forward and thank you in advance.
Regards
James
I have a couple of suggestions:
Check to see if you have setUseIntegerPositions set to true
(the default) when you draw your font. If you do, and you're scaling
it, then it can cause some odd effects similar to those that you
describe. Set it to false and see if it fixes the problem.
Reset your spritebatch's matrices before drawing the text, that way you won't need to adjust it for the scrolling.
I'd even go as far as to recommend not scaling the font if you can help it, because fonts often look a little odd after being scaled.
I'm trying to draw a MovieClip to a BitmapData so that it looks exactly the same as if I had done addChild(movieclip).
I can't seem to figure out what magic formula I need to use to keep the animation in place around it's origin.
This is the relevant bit of code:
private function update(e:Event):void
{
var bounds:Rectangle = movieClip.getBounds(movieClip);
bitmapData = new BitmapData(maxMCwidth, maxMCheight, true, 0x0);
bitmapData.draw(movieClip, new Matrix(1, 0, 0, 1, maxMCwidth - (bounds.x + bounds.width), maxMCheight - (bounds.y + bounds.height)));
bitmap.bitmapData = bitmapData;
}
Full code here: http://pastebin.com/KyU5FPeJ
And this is what the result looks like:
http://www.swfcabin.com/open/1339173476
The top animation is done using addChild(mc). The bottom animation is done using bitmapData.draw. Notice how the sword on the right doesn't move horizontally in the bottom version. Almost as if the whole animation was getting right-aligned.
Here's also a link to my flashdevelop project with the full code in case anybody wants to play around with it: https://www.dropbox.com/s/gvt4scknqdian2a/bitmapdatadrawing.zip
I just want both versions to look the same. What do I need to change to my bitmapData drawing code to make this happen?
Ok I figured it out!
The cause of the problem was that I'm not calculating maxMCwidth or maxMCheight correctly. I was going through the movieclip looking for the widest/highest single frame. BUT that doesn't take into account that the position of bounds across frames changes. To get the actual maximum width/height across the whole animation, I used this code:
maxBounds = new Rectangle();
for (var i:uint = 0; i < movieClip.totalFrames; i++)
{
var tempBounds:Rectangle = movieClip.getBounds(movieClip);
maxBounds = maxBounds.union(tempBounds);
movieClip.nextFrame();
}
Then this allowed me to fix the translation matrix:
bitmapData.draw(movieClip, new Matrix(1, 0, 0, 1, -maxBounds.x, -maxBounds.y));
And like this it works for every animation I've tested.
Ok I can't get your project to run since you didn't supply a main mxml.
However, I think I found your issue.
I don't think getBounds is returning the values you think they are.
I can't look into the skeleton swc but I have a feeling there is on object off the top or bottom of the screen in it and the way you coded it would cause it to shrink down to make it fit.
getBounds is probably adding that to the height.
bitmapData = new BitmapData(movieClip.width, movieClip.height, true, 0x0);
bitmapData.draw(movieClip, new Matrix(1, 0, 0, 1, movieClip.width/2, movieClip.height/2 ));
bitmap = new Bitmap(bitmapData);
bitmap.x = 70;
bitmap.y = 200;
Remember untested code here. :(
objectToBeMasked.mask = maskObject;
Ok, simple... but I can SEE the maskObject unless I set its alpha to 0 and then it doesn't let clicks through to objectToBeMasked
And every single tutorial that I've seen fails to mention this and how to solve it, as if it should be obvious.
How do I mask objects through AS3 so that the masks act like masks act like the ones added in the IDE?
Here is an example :
var maskedShape : Shape = new Shape();
maskedShape.graphics.beginFill(0x0);
maskedShape.graphics.drawRect(0, 0, 100, 100);
maskedShape.graphics.endFill();
addChild(maskedShape);
var maskerShape : Shape = new Shape();
maskerShape.graphics.beginFill(0x0);
maskerShape.graphics.drawRect(0, 0, 100, 100);
maskerShape.graphics.endFill();
addChild(maskerShape);
maskerShape.x = 20;
maskerShape.y = 20;
maskedShape.mask = maskerShape;
You shouldn't see the mask. Probably the mask and the masked object are not on the stage at the time you are trying to apply the mask.
Can you pass on some code here?
The easiest way is to not render your object simply bt setting visible parameter to false :
maskObject.visible = false;
so your objectToBeMasked is still masked, but do not catch mouse event, and is not rendered anymore :)