I have a Screen:
WorldScreen implements Screen, InputProcessor{
....
stageGui.addActor(storyActor);
....
#Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
}
}
and I have an Actor :
public class StoryActor extends Group {
private InputListener listener = new InputListener() {
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
event.handle();
}
}
}
When Clicking on the actor, then first the touchup from the WorldScreen is handled. Then later the touchUp from the StoryActor is handled.
How can I achieve that first the actors will be handled ?
Instead of implementing InputProcessor in your WorldScreen. Create a new class for InputProcessor for example: WorldScreenInputProcessor implements InputProcessor
After that, you can use the InputMultiplexer to handle several InputProcessors:
InputMultiplexer multiplexer = new InputMultiplexer();
//What you add first has higher priority
multiplexer.addProcessor(stageGui); //Input of your Actor
multiplexer.addProcessor(new WorldScreenInputProcessor());
Gdx.input.setInputProcessor(multiplexer);
Take a look at https://github.com/libgdx/libgdx/wiki/Event-handling#inputmultiplexer on how to use input multiplexers it should solve your problem.
Related
I am a bit confused about touch handling of libGDX. I have seen the usage of all three types.
InputProcessor:
http://www.gamefromscratch.com/post/2013/10/24/LibGDX-Tutorial-5-Handling-Input-Touch-and-gestures.aspx
public class InputDemo2 implements ApplicationListener, InputProcessor {
#Override
public void create() {
Gdx.input.setInputProcessor(this);
}
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
}
}
InputListener here:
http://www.gamefromscratch.com/post/2013/11/27/LibGDX-Tutorial-9-Scene2D-Part-1.aspx
public MyActor(){
setBounds(actorX,actorY,texture.getWidth(),texture.getHeight());
addListener(new InputListener(){
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
((MyActor)event.getTarget()).started = true;
return true;
}
});
}
InputAdapter here:
LibGdx, How to handle touch event?
public class Prac1 extends ApplicationAdapter {
#Override
public void create () {
Gdx.input.setInputProcessor(new InputAdapter(){
#Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
return true;
}
});
}
}
I don't find one different from another. Which one should I use?
InputListener
InputListener is an EventListener for low-level input events that is provided for receiving and handling InputEvents.
EventListener is an interface with a handle(Event) method that are added to actors to be notified about events. Classes that implement the EventListener interface use instanceof to determine whether they should handle the event.
An actor just needs to add an InputListener to start receiving input events.
InputProcessor
An InputProcessor is used to receive input events from the keyboard and the touch screen (mouse on the desktop). For this it has to be registered with the Input.setInputProcessor(InputProcessor) method. It will be called each frame before the call to ApplicationListener.render().
InputAdapter
InputAdapter is just an adapter class for InputProcessor. If you want to override only some methods that you're interested in, use this class.
I am creating a game wherein an apple is being shot with an arrow. The apple's location is the XY location of the user input and the arrow actor has to move to that location using the code actor.moveto. The problem is the arrow only moves only once to the user input's direction. I know that the moveTo action of the actor is updated many times per second when I called stageArrow.act in the update method so I am wondering why the arrow only moves once. Here's my code:
appleclass.java
public class AppleClass implements Screen {
Arrow arrow;
private final MainApp app;
public Image ShotImage;
public AppleClass(final MainApp app){
this.app = app;
this.stageApple = new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
this.stageArrow =new Stage(new StretchViewport(app.screenWidth,app.screenHeight , app.camera));
arrow = new ArrowClass(app);
}
#Override
public void show() {
InputMultiplexer inputMultiplexer = new InputMultiplexer();
inputMultiplexer.addProcessor(stageApple);
inputMultiplexer.addProcessor(stageArrow);
Gdx.input.setInputProcessor(inputMultiplexer);
arrow();
}
public void arrow(){
arrow.isTouchable();
stageArrow.addActor(arrow);
arrow.addAction((moveTo(Gdx.input.getX(),Gdx.input.getY(),0.3f))); //===> only executes once.
arrow.addListener(new InputListener(){
public void enter(InputEvent event, float x, float y, int pointer, Actor fromActor){
if (Gdx.input.isTouched()){
ShotImage.setVisible(true);
}
}
});}
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
update(delta);
}
public void update(float deltaTime){
stageApple.draw();
stageArrow.draw();
stageApple.act(deltaTime);
stageArrow.act(deltaTime);
}
ArrowClass.java
public class ArrowClass extends Actor {
MainApp app;
AppleClass appleClass;
public Texture arrowTexture;
public ArrowClass(final MainApp app){
this.app = app;
arrowTexture = new Texture("medievalarrow.png");
this.setSize(arrowWidth, arrowHeight);
this.setTouchable(Touchable.enabled);
this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
this.setOrigin(0,0);
}
#Override
public void draw(Batch batch, float parentAlpha) {
super.draw(batch, parentAlpha);
final float delta = Gdx.graphics.getDeltaTime();
this.act(delta);
app.batch.begin();
app.batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
app.batch.end();
}
}
Any help will be highly appreciated. Thanks.
I think the problem is because you are calling this.act(delta) in your ArrowClass' draw method. When you call Stage#act(), it will call the act method on all of its actors for you. Since you're calling it once when you draw and again when you update the stage, it's moving at twice the normal speed and that could be causing it to reach its destination prematurely.
A few other comments about your code, if I may:
First, you probably don't want two separate stages- unless you're using Scene2D.UI, you would normally have a single stage with Arrow and Apple added to it as actors.
Second, when you override Actor#draw(), you should use the batch it passes you to do the rendering instead of using the one from app. You also don't want to call begin() and end() inside your draw method- these are 'expensive' and you only want to call them once per frame. However, if you just use the batch that is passed to draw(), the Stage class will handle beginning and ending for you and you won't need to call them explicitly.
Third, you actually don't need to call super.draw(batch, parentAlpha) because it's an empty method in the Actor class.
Thus, your class could be simplified to the following:
public class ArrowClass extends Actor {
AppleClass appleClass; // You never set this; you may not need it
Texture arrowTexture;
public ArrowClass(MainApp app, arrowWidth, arrowHeight) {
arrowTexture = new Texture("medievalarrow.png");
this.setSize(arrowWidth, arrowHeight);
this.setTouchable(Touchable.enabled);
this.setBounds(app.screenWidth*0.45f,0,arrowWidth,arrowHeight);
this.setOrigin(0,0);
}
#Override
public void draw(Batch batch, float parentAlpha) {
batch.draw(arrowTexture, getX(),getY(),getWidth(),getHeight());
}
}
I don't know how to detect when the user drag event is end or not so I decide to do like this
protected class Input extends DragListener{
boolean dragging=false;
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
return true;
}
#Override
public void touchDragged(InputEvent event, float x, float y, int pointer) {
if(!dragging)dragging=true;
*my game logic*
.
.
.
}
#Override
public void touchUp(InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("touch up","");
if (dragging) {
*my game logic*
.
.
.
}
}
}
I try my class by drag and touch up ,nothing happen.
I drag again and nothing happen. then I tap and the console is print "touchUp" two time.
Is there anything else to detect it
In the interface GestureListener that resides in GestureDetector there is a method pan and panStop. You should implement that interface, add all the methods from it and use pan for your dragging behaviour and panStop for the solution to your question. The methods register for both touch and mouse as well as multiple finger touches.
In my game in Libgdx I want to change ImageButton image on click. I think this should be easy, but I have lost hours on this. :)
public void show() {
buttonSound = new ImageButton(skin.getDrawable("sound_off"));
buttonSound.addListener(new onSoundListener());
}
class onSoundListener extends InputListener {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
return true;
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
buttonSound.setBackground(skin.getDrawable("btn_sound"));
}
}
This doesn't work. Can someone help me with this?
Thanks
I found solution for my problem by setting checked image
ImageButton (Drawable imageUp, Drawable imageDown, Drawable imageChecked)
and then
if (gameData.isSound())
buttonSound.setChecked(false);
else
buttonSound.setChecked(true);
I have a class Bubble that extends Actor.
public Bubble(MyGdxGame game,Texture texture){
this.game=game;
setPosition(0,0);
setSize(32,32);
gameObject=new GameObject("","bubble");
direction=new MovementDirection();
sprite=new Sprite(texture);
setTouchable(Touchable.enabled);
setWidth(sprite.getWidth());
setHeight(sprite.getHeight());
setBounds(0,0,sprite.getWidth(),sprite.getHeight());
addListener(new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("BUBBLE", "touchdown");
return true; // must return true for touchUp event to occur
}
public void touchUp (InputEvent event, float x, float y, int pointer, int button) {
Gdx.app.log("BUBBLE", "touchup");
}
});
}
This is in a class that implements Screen
public void show() {
// TODO Auto-generated method stub
super.show();
//2 bubbles test
gameStage=new Stage(MyGdxGame.WIDTH,MyGdxGame.HEIGHT,true);
Gdx.input.setInputProcessor(gameStage);
for (int i=0; i<10; i++){
Bubble b=new Bubble(game,Assets.bubbleTexture);
b.randomize();
gameStage.addActor(b);
}
//if (bubbleList==null)
// createBubbles();
}
Am I going about this the wrong way by adding the listener # the bubble level? (It seems creating an InputListener for every bubble I spawn is a little crazy).
According to : http://libgdx.l33tlabs.org/docs/api/com/badlogic/gdx/scenes/scene2d/Actor.html
Actor has a touchUp() and touchDown event - but complains when i try to override them (which lead me to believe they dont exist). Overriding these I feel would be a better approach
The docs you linked to are outdated.
Those methods were deprecated and removed in favor of using InputListeners.
In your example if you want to use the same InputListener instance for all instances of your Actor class (Bubble) then you can just implement the InputListener to refer to the Actor class instance using inputEvent.getRelatedActor() and then instantiate one such InputListener as a static member of Bubble and pass it in the constructor to addListener.
class Bubble extends Actor{
private static InputListener bubbleListener= new InputListener() {
public boolean touchDown (InputEvent event, float x, float y, int pointer, int button) {
Bubble b = (Bubble) event.getRelatedActor();
b.doSomething();
...
return true; //or false
}
}
public Bubble(){
addListener(bubbleListener);
...
}
...
}