Slick Forums

Discuss the Slick 2D Library
It is currently Wed May 22, 2013 4:09 pm

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Tue Jul 10, 2012 6:24 pm 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
Wow, there must be something i reaaaally don't understand in Slick, or something i must be missing.

I'm making a game with states, a menu, another menu, then the main state and a gameoverstate.
I've made changes on my menu in order to incorporate new stuff, and now everything is broken.

I add some components on my menu, this components being "active" and clickable with the mouse (basically they update the abstractcomponent and override the mouserelease method).
Now i see in my MainGameState that events are being captures by AbstractComponent created in my MenuState :shock: :shock: (components that are not supposed to exist in my current state, nor even rendered in the current render method)

I thought the whole point of having separate states was to have separate render/update methods and thus no interactions.

I'm assuming the idea is to have kind of layers, so is this behaviour normal?
Does that mean that all render/update method are always called?
I really don't understand this?
I'm also assuming if it is that there's still a way to kill the previous states...?
Am I doing something wrong?
Am I asking to much questions? :)

_________________
Seventeen


Top
 Profile  
 
PostPosted: Tue Jul 10, 2012 7:43 pm 
Offline
Slick Zombie

Joined: Sat Jan 27, 2007 7:10 pm
Posts: 1469
Are you sharing the same components across states?
Can you post a test case?

This shouldn't happen. It sounds like you've got something wrong in your code, or you've discovered a bug with Slick's AbstractComponent class.


Top
 Profile  
 
PostPosted: Tue Jul 10, 2012 8:04 pm 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
Hi davedes, thanks for taking the time!

This is really weird, i've pulled two versions from my SVN and kind of "narrowed" the issue.

The problem lies here :

This is my "menuview" :

Code:
public class TeamView extends BasicGameState implements ComponentListener {

   ...

   @Override
   public void enter(GameContainer container, StateBasedGame game)
         throws SlickException {

         ...

      /*
      buttons.add(new MenuButton(container,this,475,300,150,30,"test","test"));
      buttons.add(new MenuButton(container,this,320,340,150,30,"test2","test2"));
      buttons.add(new MenuButton(container,this,630,340,150,30,"test3","test3"));

      */
   }
   
   ...


}


This is the "MenuButton" :

Code:
package com.projectx.view.components;

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

import com.projectx.view.Resources;

public class MenuButton extends BaseComponent {
   
   private static final Color transparentwhite = new Color(1,1,1,1);
   
   private String text;
   private String smalltext;

   public MenuButton(GUIContext container, ComponentListener listener, int x, int y, int width, int height, String text, String smalltext) {
      super(container, listener, x, y, width, height);
      this.text = text;
      this.smalltext = smalltext;
      visible = true;
      
   }

   @Override
   public void render(GUIContext gc, Graphics gr) throws SlickException {
      
      
      gr.setLineWidth(1);
      if (over){
         gr.drawGradientLine(x, y, Color.white, x-8, y, transparentwhite);
         gr.drawGradientLine(x, y, Color.white, x+80, y, transparentwhite);
         gr.drawGradientLine(x, y, Color.white, x, y-8, transparentwhite);
         gr.drawGradientLine(x, y, Color.white, x, y+8, transparentwhite);
         
         gr.drawGradientLine(x+width, y+height, Color.white, x+width-80, y+height, transparentwhite);
         gr.drawGradientLine(x+width, y+height, Color.white, x+width+8, y+height, transparentwhite);
         gr.drawGradientLine(x+width, y+height, Color.white, x+width, y+height-8, transparentwhite);
         gr.drawGradientLine(x+width, y+height, Color.white, x+width, y+height+8, transparentwhite);
      }
      
      Resources.fontMicro.drawString(x+width/2-Resources.fontMicro.getWidth(smalltext)/2, y+2, smalltext);
      Resources.font.drawString(x+width/2-Resources.font.getWidth(text)/2, y+10, text);

   }

}


The BaseComponent is a small add up to the abstractcomponent :

Code:
package com.projectx.view.components;

import org.newdawn.slick.gui.AbstractComponent;
import org.newdawn.slick.gui.ComponentListener;
import org.newdawn.slick.gui.GUIContext;

public abstract 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;
   }

}


If i uncomment the three lines creating the buttons (not even actually rendering them in the view) when i go to my gamestate, when i click, it goes in the mouseReleased method of the BaseComponent of the MenuButton (or even sometimes some other components of the menu, which are never added nor rendered into the gameview), since the test is ok the menuview is notified, and the event consumed, and my game is not working anymore :).
Since the GameContainer is shared between the states, maybe there's something there?
Also, i don't get why the mousereleased function is called on every component everytime, why is the event not bound to the actual size and placement of the component?

This is really a bumer for me, hope you can help me out, if you need more information, feel free to tell me. I know i can workaround this, but it's just plain weird...

(Also i tried pulling the last development version you guys are working on, and apparently, same problem)

_________________
Seventeen


Top
 Profile  
 
PostPosted: Wed Jul 11, 2012 7:51 am 
Offline
User avatar

Joined: Wed Jun 20, 2012 8:10 pm
Posts: 54
Hi!

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!


Attachments:
File comment: Complete project with the bug
src.zip [6.44 KiB]
Downloaded 15 times

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

All times are UTC


Who is online

Users browsing this forum: No registered users and 4 guests


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:  
Powered by phpBB® Forum Software © phpBB Group