I have a Deck Panel with AnimationEnabled(true). I want to know when the animation completes when i change the deck in order to perform other tasks.
I guess the answer would be there is no way to do it
Did you try subclassing DeckPanel and overriding onComplete()?
public MyDeckPanel extends DeckPanel{
#Override
protected void onComplete(){
super.onComplete();
//What you want to do once the animation completes
}
}
Related
My problem is I want an actor to do an action (in this case a fade) and just after the end of the action, switch to the game screen. But the action is finished not complete, but quickly changed the game screen.
I want to wait to complete this action before changing the screen .. And in general, I wonder how I can make waiting instructions in the game, because it is sometimes good to want to allow some time before anything happens.
myActor.addAction(Actions.fadeIn(2));
setScreen(AnotherScreen);
Use the static imports for actions, way easier.
import static com.badlogic.gdx.scenes.scene2d.actions.Actions.*;
Actor.addAction(sequence(fadeOut(2f), run(new Runnable() {
public void run () {
System.out.println("Action complete!");
}
});
Put the code you want to run in the runnable.
For more info,
https://github.com/libgdx/libgdx/wiki/Scene2d#actions
What you have to do is create an Action subclass and override Action#act where you will call setScreen(AnotherScreen);.
Then, use Actions#sequence to wrap both actions into a single SequenceAction object.
Action switchScreenAction = new Action(){
#Override
public boolean act(float delta){
setScreen(AnotherScreen);
return true;
}
};
myActor.addAction(Actions.sequence(
Actions.fadeIn(2)
, switchScreenAction
));
For more info, check out: https://github.com/libgdx/libgdx/wiki/Scene2d#complex-actions
I started a project with libgdx and I have a GameStateManager for my GameStates Menu and Play.
If I run the project it shows the Menu and then I can click a button to open the Play GameState.
The Problem is, that when I ended the Game it should show the Menu State again, but I get a black screen. I tested if the render() method is started (with System.out...) and the render() method in Menu is starting.
I am not shure why I get a black screen when I "reopen" the Menu state. Maybe its not working because I use Box2D in Play but I dont know.
Here some code:
This is the method in Play which should open the Menu if the player is at the end:
public void playerEnded() {
gsm.setState(GameStateManager.MENU);
}
Maybe you can tell me, if I have to end box2d things or so.
I hope someone can help me, and if you want more code - no problem.
Your custom GameStateManager should extend this class:
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/Game.html
To change screens you should be using Game.setScreen(Screen screen)
Each different screen should be an implementation of Screen.
So the way it works in my libGDX projects is such that GameScreen extends Screen, and MenuScreen extends Screen. That way I can change what draws on what screen.
This all goes back to interfaces and polymorphism, so if you don't get those concepts, just give it a quick google and you'll get an idea what you need to do.
Chances are that your are defining a
Stack<GameState> gameStates
in your GameStateManager to manage your GameStates.
If so, you could do some reading on using a Stack. Anyway, here's what could do to solve your problem:
I'm assuming you have the following structure in your GamestateManager;
public void setState(int state){
popState();
pushState(state);
}
public void pushState(int state){
gameStates.push(getState(state));
}
public void popState(){
GameState g = gameStates.pop();
g.dispose();
}
private GameState getState(int state){
if(state == MENU) return new Menu(this);
if(state == PLAY) return new Play(this);
return null;
}
When you click your start button in your Menu-GameState, you'll want to launch the Play-GameState.
Now, instead of using the setState method, which removes the top state (pop) and then pushes the new state. Try using only the pushState method. This will put your new Play-GameState on top of your Menu-GameState in the GameState-Stack.
When you're done playing, you can pop your Play-GameState and the Menu-GameState should reappear. But this time it won't instantiate a new Object, but reuse the one you used when you started the game.
// in the Menu-GameState:
public void startPlay() {
gsm.pushState(GameStateManager.PLAY);
}
// in the Play-GameState:
public void playerEnded() {
gsm.popState();
}
This won't affect gameplay performance as you would render and update your game with only the GameState that is on top of the Stack, like this:
public void update(float dt) {
gameStates.peek().update(dt);
}
public void render() {
gameStates.peek().render();
}
The peek method takes the GameState from the top of the Stack, but leaves it there.
The only downside is that the Menu-Gamestate would stay in-memory during your Play-State.
Also, if this method works, you could still do it your way, but you should check the way your Menu-GameState is instantiated and identify problems when it's instantiated twice.
I implemented a similar StageManager in my game. If you are using viewports/cameras in your game, then it is likely that when you go back to your menu state, the viewport is still set to the Game state's viewport.
For my app, I had my State class have an activate() method which would be called whenever a state became the active state:
public void activate(){
stage.getViewport().update(Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
}
This has long bothered me.
When using stage resize, you could say something like this:
public class Preload extends MovieClip
{
protected var main:Main;
public function preloader()
{
this.main = new Main();
this.addChild(this.main);
stage.addEventListener(Event.RESIZE, this.onResize);
}
protected function onResize(e:Event): void
{
this.main.x = stage.stageWidth>>1;
this.main.y = stage.stageHeight>>1;
}
}
What about if Main needs to also resize? I have many systems which respond to a resize event and I do not know if I should simply add a stage Event.RESIZE listener to every screen or if this should be controlled from a single location.
For example, add this.main.resize() to the onResize listener above then implement an IResizable interface on my screens for example?
What is best practice?
EDIT: Or should resize be part of something more generic, like invalidate()
For performance it's better to have only 1 Event.RESIZE listener in your document class. Then propagate the event to all your sub classes and children with functions, or even better with the wonderful Signals framework by Robert Penner.
If you need to scale your document class the easiest way is to put all your content inside a Sprite and scale that instead.
I am trying to implement a simple animation with libGDX and I am currently stuck on one thing. Lets say I have a bunch of sprites which take some time to finish. For example, around 30 sprites like this link: https://github.com/libgdx/libgdx/wiki/2D-Animation
However, before the animation completes some key is pressed. For smooth animation I want the 30 frames to be completed before I start the next set of animation, to prevent an abrupt stop.
So my question is how do I achieve it this in libGDX? My current idea is to extend the Animation class, which would keep track of how frames I have and how many have been rendered and then display the rest. Or use the isAnimationFinished(float stateTime) function (though I haven't had luck using that).
The examples I have seen like superjumper have very few animations and don't really change that much.
Also, is there a way to hold the list of sprites from a TextureAtlas.createSprites method and use those with the Animation class? If not, whats the purpose of providing this function?
Thanks
You can use
animation.isAnimationFinished(stateTime);
To see if your animation is finished.
For the sprites : personnaly I use TextureRegion from a TextureAtlas and I store them in an array for my animation
I create a class AnimatedImage that extends Image to automate spriting in Image. My code will be like this:
public class AnimatedImage extends Image{
private Array<Array<Sprite>> spriteCollection;
private TextureRegionDrawable drawableSprite;
private Animation _animation;
private boolean isLooping;
private float stateTime;
private float currentTime;
public AnimatedImage(Array<Array<Sprite>> _sprites, float animTime, boolean _looping){
// set the first sprite as the initial drawable
super(_sprites.first().first());
spriteCollection = _sprites;
// set first collection of sprite to be the animation
stateTime = animTime;
currentTime = 0;
_animation = new Animation(stateTime, spriteCollection.first());
// set if the anmation needs looping
isLooping = _looping;
drawableSprite = new TextureRegionDrawable(_animation.getKeyFrame(currentTime));
this.setDrawable(drawableSprite);
}
public void update(float delta){
currentTime += delta;
TextureRegion currentSprite = _animation.getKeyFrame(currentTime, isLooping);
drawableSprite.setRegion(currentSprite);
}
public void changeToSequence(int seq){
// reset current animation time
resetTime();
_animation = new Animation(stateTime, spriteCollection.get(seq));
}
public void changeToSequence(float newseqTime, int seq){
_animation = new Animation(newseqTime, spriteCollection.get(seq));
}
public void setRepeated(boolean _repeat){
isLooping = _repeat;
}
public boolean isAnimationFinished(){
return _animation.isAnimationFinished(currentTime);
}
public void resetTime(){
currentTime = 0;
}
}
changetosequence method will make new Animation that will be used to update the current TextureRegionDrawable at the update method. resetTime will reset the total time for the animation when you call changeToSequence. You could add the event listener to call changeToSequence method.
Here is the example:
private AnimatedImage _img;
then I add the InputListener like this:
_img.addListener(new InputListener(){
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button){
_img.changeToSequence(1);
return true;
}
});
Hope it helps.
Use tween engine for this kind of animation. Its well documented and libgdx supports it .. Google about it , and you can find bunch of examples using libgdx .. Hope it will help you !!
I'm writing code for a 3D graph, and I want the scene graph to update when the user presses a JButton. I'm trying to use a Behavior class, but I can't find any information on using swing events to wake up the behavior. I would REALLY appreciate any help! Thank you!!
You can use a special behavior object which contains a queue of Runnables. You can then post runnables to the behaviour and wake it up. You will have to sort out proper synchronisation so the behaviour only goes to sleep when there are no more commands in the queue, but it should work.
Make the class into a singleton to be able to run Runnable's inside the BehaviorScheduler, analogous to the SwingUtilities.invokeLater() method.
public class ThreadTransferBehavior extends Behavior {
private final static int POST_ID = 9997;
private final WakeupOnBehaviorPost m_wakeupPost = new WakeupOnBehaviorPost(this, POST_ID);
private final Stack<Runnable> commands;
public synchronized void processStimulus(Enumeration i) {
while(!commands.isEmpty()) commands.pop().run();
wakeupOn(m_wakeupPost);
}
public synchronized void queueCommand(Runnable r) {
commands.push(r);
postId(POST_ID);
}
}