Slick Forums

Discuss the Slick 2D Library
It is currently Thu Oct 18, 2018 5:26 am

All times are UTC




Post new topic Reply to topic  [ 8 posts ] 
Author Message
PostPosted: Sun Jul 15, 2012 9:55 am 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
Hi!
I had no answer on the help post, so i'm putting this here, just in case this actually is a bug.

I made a little project to pinpoint the bug (which i think it is).
It's a basic statebasedgame with two state. First one has a big abstractcomponent which triggers the start of the second one, the second one only capturing mouse events.
The first state has a component covering almost all the space. When you click on the second state, bam! The component on the first state actually catches it, and it never goes onto the second one (where there is actually no component rendered).
I've attached the source code in a zip, and here it is in this message :

TestApp.java
Code:
package slicktest;

import org.newdawn.slick.AppGameContainer;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.StateBasedGame;

public class TestApp  extends StateBasedGame{
   
   private static TestApp _thisInstance;
   
   public static TestApp getInstance() {
      return _thisInstance;
   }
   
   public static final int MENUSTATE = 1;
   public static final int MAINSTATE = 2;

   public TestApp(String name) {
      super(name);
      
      _thisInstance = this;

      this.addState(new MenuState());
        this.addState(new MainState());
        this.enterState(MENUSTATE);
   }

   @Override
   public void initStatesList(GameContainer arg0) throws SlickException {
      // TODO Auto-generated method stub
      
   }
   
   public static void main(String[] args) {

      AppGameContainer app;
      try {
         app = new AppGameContainer(new TestApp("test"));
         app.setDisplayMode(640, 480, false);
         app.setTargetFrameRate(60);
         app.start();
      } catch (SlickException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }

   }

}


MenuState.java
Code:
package slicktest;

import java.util.ArrayList;
import java.util.List;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.ComponentListener;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

import component.BaseComponent;

public class MenuState extends BasicGameState implements ComponentListener {
   
   List<BaseComponent> components = new ArrayList<BaseComponent>();

   @Override
   public void init(GameContainer gc, StateBasedGame arg1) throws SlickException {
      
      BaseComponent b = new BaseComponent(gc,this,5,5,630,470);
      b.setVisible(true);
      components.add(b);
      
   }

   @Override
   public void render(GameContainer gc, StateBasedGame arg1, Graphics gr) throws SlickException {
      
      for (BaseComponent b : components){
         b.render(gc, gr);
      }
      
   }

   @Override
   public void update(GameContainer arg0, StateBasedGame arg1, int arg2) throws SlickException {
      // TODO Auto-generated method stub
      
   }

   @Override
   public int getID() {
      return TestApp.MENUSTATE;
   }

   @Override
   public void componentActivated(AbstractComponent arg0) {
      System.out.println("Button activated!");
      
      TestApp.getInstance().enterState(TestApp.MAINSTATE);
      
   }


}


MainState.java
Code:
package slicktest;

import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.state.BasicGameState;
import org.newdawn.slick.state.StateBasedGame;

public class MainState extends BasicGameState {
   
   

   @Override
   public void mouseReleased(int button, int x, int y) {
      System.out.println("Captured in mainstate");
   }

   @Override
   public void init(GameContainer gc, StateBasedGame arg1) throws SlickException {
      
      
      
   }

   @Override
   public void render(GameContainer gc, StateBasedGame arg1, Graphics gr) throws SlickException {

      gr.drawRect(50, 50, 500, 400);
      gr.drawString("You are in the main state", 200, 240);
      
   }

   @Override
   public void update(GameContainer arg0, StateBasedGame arg1, int arg2) throws SlickException {
      // TODO Auto-generated method stub
      
   }

   @Override
   public int getID() {
      return TestApp.MAINSTATE;
   }


}


BaseComponent.java
Code:
package component;

import org.newdawn.slick.Color;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.ComponentListener;
import org.newdawn.slick.gui.GUIContext;

public class BaseComponent extends AbstractComponent {

   protected int x, y, height, width;

   protected boolean over;

   protected boolean visible = false;

   public BaseComponent(GUIContext container, ComponentListener listener, int x, int y, int width, int height) {
      super(container);
      this.x = x;
      this.y = y;
      this.height = height;
      this.width = width;
      
      if (listener != null){
         addListener(listener);
      }
         
   }

   @Override
   public int getHeight() {
      return height;
   }

   @Override
   public int getWidth() {
      return width;
   }

   @Override
   public int getX() {
      return x;
   }

   @Override
   public int getY() {
      return y;
   }

   @Override
   public void setLocation(int X, int Y) {
      this.x = X;
      this.y = Y;
   }

   @Override
   public void mouseReleased(int button, int x, int y) {

      if (listeners.size() > 0 && visible && x > this.x && x < (this.x + this.width)
            && y > this.y && y < (this.y + this.height)){
         notifyListeners();
         consumeEvent();
      }

   }

   @Override
   public void mouseMoved(int oldx, int oldy, int newx, int newy) {

         if (newx > this.x && newx < (this.x + this.width)
               && newy > this.y && newy < (this.y + this.height)){
            over = true;   
         }
         else{
            over = false;
         }


   }

   public boolean isVisible() {
      return visible;
   }

   public void setVisible(boolean visible) {
      this.visible = visible;
   }

   @Override
   public void render(GUIContext gc, Graphics gr) throws SlickException {
      
      gr.setColor(Color.white);
      gr.drawRect(x, y, width, height);
      gr.drawString("TEST!!!!", x+width/2-gr.getFont().getWidth("TEST!!!!"), y+height/2-10);
      
   }

}


Can you confirm that it is actually a bug or pinpoint what is wrong about this code?

Thanks!

_________________
Seventeen


Top
 Profile  
 
PostPosted: Sun Jul 15, 2012 1:06 pm 
Offline
Regular

Joined: Sun Oct 30, 2011 4:47 pm
Posts: 184
Location: Mittweida, Saxony, Germany
I think you misunderstood the concept of the game states. There is always only one game state active in a state based game. And only the active on catches anything.

Nitram

_________________
http://illarion.org


Top
 Profile  
 
PostPosted: Tue Jul 17, 2012 7:55 am 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
Nitram wrote:
I think you misunderstood the concept of the game states. There is always only one game state active in a state based game. And only the active on catches anything.

Nitram


So I did actually understand the concept, and i'm pin pointing the fact that in this example the first state catches events whereas it's not the active state!

I think i wasn't actually really clear on my first post (i'm sorry, i already explained the whole thing here : viewtopic.php?f=3&t=5235), i just took the last post and realize maybe the example is not really clear.

When i click on the MenuState, i have :
Button activated!

And it goes to the MainState.
Now in the main state, if i click on the "center" of the frame, i have :
Button activated!

The same, but this button is only supposed to exist on the first state (MenuState)!

I have to click outside the bounds of the component (new BaseComponent(gc,this,5,5,630,470);), to actually see the :
Captured in mainstate

So you seem to say this is not actually the behaviour we should have, hence .... bug?

_________________
Seventeen


Top
 Profile  
 
PostPosted: Wed Jul 18, 2012 4:45 pm 
Offline

Joined: Sat Jul 14, 2012 2:35 am
Posts: 19
try to put this in your MenuState:

Code:
   @Override
    public void leave(final GameContainer container, final StateBasedGame game) throws SlickException {
        for (final BaseComponent b : components) {
            b.setVisible(false);
        }
    }


i think the basicCompontents dont care about states, they are still active even if they are not shown via render method.

you shout use enter and leave to activate and deactivate the input in the current state... you might want to have some inputs active in all states e.g. the capture screenshot input. you dont want those functions to be placed in all states separately.

greetz Ben


Top
 Profile  
 
PostPosted: Thu Jul 19, 2012 5:05 pm 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
ben wrote:
try to put this in your MenuState:

i think the basicCompontents dont care about states, they are still active even if they are not shown via render method.

you shout use enter and leave to activate and deactivate the input in the current state... you might want to have some inputs active in all states e.g. the capture screenshot input. you dont want those functions to be placed in all states separately.

greetz Ben


Hi Ben,

It will indeed work, it's what i did to make it work, still, i don't really understand the point of having component working in every state. I thought the point of the states was to be separate. Plus, in terms of resources it seems weird to always check all the component, whether there are here or not. I i were to have a lot of component on one state, than on the second one, the checks would be made on all those components... Strange isn't it?

Anyway, was just wondering if it was actually a bug, and i don't understand your example where it is actually useful (screenshot would be some kind of key press not a button per se).

_________________
Seventeen


Top
 Profile  
 
PostPosted: Thu Jul 19, 2012 5:30 pm 
Offline

Joined: Sat Jul 14, 2012 2:35 am
Posts: 19
Seventeen wrote:
Hi Ben,

It will indeed work, it's what i did to make it work, still, i don't really understand the point of having component working in every state. I thought the point of the states was to be separate. Plus, in terms of resources it seems weird to always check all the component, whether there are here or not. I i were to have a lot of component on one state, than on the second one, the checks would be made on all those components... Strange isn't it?

Anyway, was just wondering if it was actually a bug, and i don't understand your example where it is actually useful (screenshot would be some kind of key press not a button per se).


the baseComponent u are using is not more than an InputAdapter, thus receiving input from the Input class. since u are overriding mouseReleased in this method and call inside the notifyListeners method u always fire an event for mouseRelease on this baseComponent... perhaps make an focus- and/or active check before?

i recommend to download the slick-sources.jar and have a look at the classes u use to inheritate...

greetz Ben


Top
 Profile  
 
PostPosted: Fri Jul 20, 2012 7:04 am 
Offline
Regular

Joined: Sun Oct 30, 2011 4:47 pm
Posts: 184
Location: Mittweida, Saxony, Germany
Oh wow, that is bad.

This slick gui components are even worse then I thought. :wink: They fetch the input data directly from the game container and don't care at all if they are linked to a game state or not.
You really have to disable them by hand once you leave the game state in question.

This may work for simple GUIs. If you want something more complex you will need to use one of the GUI frameworks supporting Slick, like TWL or Nifty-GUI.

And yes: its a bug.

Nitram

_________________
http://illarion.org


Top
 Profile  
 
PostPosted: Sat Jul 21, 2012 11:22 am 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
Nitram wrote:
Oh wow, that is bad.


Thank you! I'm not the only one to think so!

Nitram wrote:
And yes: its a bug.

Nitram


I'm guessing you're assuming/wanting this to be a bug, but is it an actual bug? :lol:

@ben : i'm aware now of how the system works, i'm just thinking this is a lot of processing/testing for one simple click. Even if i were to put active/inactive state (which i'm already doing!), i would still have to state a gazillion of times assuming i have a bunch of component in the same state.
Anyway, it's not THAT important, just wanted to put that out there.

_________________
Seventeen


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 8 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB® Forum Software © phpBB Group