Slick2D White Rectangle instead image!?

Hi all! So now I making button for my own game and I have really strange problem.
Currently my button load three images, as you can see:


buttonIdle = new Image("res/images/buttons/" + buttonSize + "IdleButton.png", false, Image.FILTER_NEAREST);
buttonDisabled = new Image("res/images/buttons/" + buttonSize + "DisabledButton.png", false, Image.FILTER_NEAREST);
buttonHighLight = new Image("res/images/buttons/" + buttonSize + "HighLightButton.png", false, Image.FILTER_NEAREST);

My problem is with disabled button image. If disabled button image ‘buttonDisabled’ loads before button highlight image it working correctly, but if disabled button image loads after button highlight image, as you can see here:


buttonIdle = new Image("res/images/buttons/" + buttonSize + "IdleButton.png", false, Image.FILTER_NEAREST);
buttonHighLight = new Image("res/images/buttons/" + buttonSize + "HighLightButton.png", false, Image.FILTER_NEAREST);
buttonDisabled = new Image("res/images/buttons/" + buttonSize + "DisabledButton.png", false, Image.FILTER_NEAREST);

Then if button is disabled I getting white rectangle instead disabled button image. I don’t know why this happening ??? I tried some things to fix that(like make format of image to 24bit and etc.) but it not helped at all! >:(
Maybe someone can help me? :slight_smile:

Note: I using Slick2D game library.

Ok, I got It. :smiley: all problem was that I intializing button on state ‘enter’ method, but I need initialize it on ‘init’ method. But why I can’t correcly initialize button from state ‘enter’ method??

Looking here at the docs, it says that all resource loading should be done in the init method. Since you were loading the images from the enter method, that’s where it was going wrong.

http://slick.ninjacave.com/javadoc/org/newdawn/slick/state/GameState.html#enter(org.newdawn.slick.GameContainer, org.newdawn.slick.state.StateBasedGame)

Depends on what you’re loading and why.

init() is fired as soon as your program launches, regardless if you’re in that state or not. Where as enter() only fires when you enter a state, but every time you enter. So, if you want to load something in that state when the program launches, you want to stick it in init(), else it should be in your enter() method. If you have a complex multistate game you may end up loading tons, and tons of stuff into memory the end-user may never even use in that session. It’s best to put as much in enter() as you can get away with.

Of course, that all goes out the window if you have a basic game and need to load everything all at once anyway, then you can stick it all in init() and then use enter() to reset game logic (for new games and such). But in a game like mine, if I stuck all my stuff in enter() into init() the game would overload and crash. :smiley:

EDIT: Here’s Retro-Pixel Castle’s main menu loader classes, for an example of what I mean. Yes, you reload all the main menu resources every time you go into the main menu (slightly increasing load time). But if it was under init, you’d be loading them at launch. For the main menu, that’d be fine. But if all my states were like that it would be problematic without a proper resource loader.


	public void init(GameContainer gc, StateBasedGame sbg) throws SlickException{
		this.gc = gc;
	}

	public void enter(GameContainer gc, StateBasedGame sbg) throws SlickException{
		loadState();
		Game.setDisplay();
		setGUI();
		clearGUI();
		showMainMenuGUIMain = true;
		transition.enter(15);
		sound.playMain();
		Game.setWorldScale(2);
	}

	private void loadState() throws SlickException{
		input = gc.getInput();
		input.enableKeyRepeat();
		mouse = new Rectangle(0,0,1,1);
		
		save = new SaveModule();
		clock = new ClockModule();
		font = new FontModule();
		transition = new TransitionModule();
		map = new MapModule();
		miniMap = new MiniMapModule();
		shadow = new ShadowModule();
		lighting = new LightingModule();
		object = new ObjectModule();
		clouds = new CloudsModule();
		background = new BackgroundModule();
		sound = new SoundModule();
		
		//TODO: This needs removed someday and replaced with the random map loader.
		save.initController("OfficialMaps","TheQuietForest");
		Calendar cal = Calendar.getInstance();
		clock.initController();
		clock.setHour(cal.get(Calendar.HOUR_OF_DAY));
		map.initController();
		miniMap.initController();
		font.initController();
		transition.initController(gc);
		shadow.initController();
		lighting.initController();
		object.initController();
		clouds.initController();
		background.initController();
		sound.initController(true);

		guiMain = new Main();
		guiMainDisclaimer = new MainDisclaimer();
		guiPlaySelectMap = new PlaySelectMap();
		guiNewMap = new MapEditorNewMap(gc);
		guiNewMapDeleteWarning = new MapEditorNewMapDeleteWarning();
		guiLoadMap = new MapEditorLoadMap();
		guiLoadMapDeleteWarning = new MapEditorLoadMapDeleteWarning();
		guiCredits = new Credits();
		guiGenericMessage = new GenericMessage();
		pillar = new Image("res/GUI/mainMenu/pillar.png", false, Image.FILTER_NEAREST);
		steamURL = new GUIButtonClickableText("steamURL", 1);
		websiteURL = new GUIButtonClickableText("websiteURL", 1);
		twitterURL = new GUIButtonClickableText("twitterURL", 1);

		map.centerMap((map.getMapFullWidth()/2)*-1,(map.getMapFullHeight()/2)*-1);
		floatXSpeedCap = Game.randomInt(5)+5;
		floatYSpeedCap = Game.randomInt(5)+5;
		floatXDirection = Game.randomInt(2);
		floatYDirection = Game.randomInt(2);
		
		showMainMenuGUIMain = false;
		showMainMenuGUIMainDisclaimer = false;
		showMainMenuGUIPlaySelectMap = false;
		showMainMenuGUIMapEditorNewMap = false;
		showMainMenuGUIMapEditorNewMapDeleteWarning = false;
		showMainMenuGUIMapEditorLoadMap = false;
		showMainMenuGUIMapEditorLoadMapDeleteWarning = false;
		showMainMenuGUIGenericMessage = false;
		
		debug = false;
	}

Thanks for replies :wink: , but how I can load state(I mean, that appears ‘loading’ text while all loading doing ‘enter’ method)?? And after all resources are loaded and objects are initialized, state shows up. :stuck_out_tongue:

RPC actually doesnt have a resource loader at all (yet), I created a “transition” class that pops the load screen up while enter() is running and loading all the state’s crap.


package rpc;

import java.util.WeakHashMap;

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

import rpc.launcher.Game;

public class TransitionModule {
	private static WeakHashMap<Integer, TransitionModule> stateInstance = new WeakHashMap<Integer, TransitionModule>();

	FontModule font;
	
	private GameContainer gc;
	private Color fade = new Color(0,0,0,255);
	private boolean fadeIn = false;
	private boolean fadeOut = false;
	private boolean fadeOutComplete = false;
	private boolean fadeOutCheck = false;
	private boolean fadeOnly = false;
	private int fadeAmount = 0;
	private boolean controlLockout = false;
	private int stateID = 0;
	private int fadeOutSpeed, fadeInSpeed = 25;
	
	public TransitionModule(){stateInstance.put(Game.getCS(), this);}
	public void initController(GameContainer gc) throws SlickException{
		font = FontModule.getState();
		this.gc = gc;
	}
	
	public void enter(int i){
		fadeInSpeed = i;
		fadeAmount = 300;
		fadeIn = true;
	}
	
	public void startTransition(String state, int o, boolean fade){
		fadeOutSpeed = o;
		fadeOut = true;
		if (fade){this.fadeOnly = true;}
		if (state.equals("splashState")){stateID = 0;}
		if (state.equals("mainMenuState")){stateID = 1;}
		if (state.equals("mapEditorState")){stateID = 2;}
		if (state.equals("playState")){stateID = 3;}
		if (state.equals("exit")){stateID = 10;}
	}
	
	public void update(StateBasedGame sbg){
		// Start fade
		if (fadeOut){
			controlLockout = true;
			fadeAmount += fadeOutSpeed;
			fade = new Color(0,0,0,fadeAmount); 
		}
		
		// Detect fade is completed.
		if ((fadeOut) && (fadeAmount >= 300)){
			fadeOut = false;
			fadeOutComplete = true;
			if (fadeOnly){fadeOutCheck = true;}
		}
		
		// Fade in slowly
		if (fadeIn){
			controlLockout = true;
			fadeAmount -= fadeInSpeed; 
			fade = new Color(0,0,0,fadeAmount);
		}
		if ((fadeIn) && (fadeAmount <= 0)){
			controlLockout = false;
			fadeIn = false;
			fadeAmount = 0;
		}
		
		// Exit state, reset FadeOutComplete flag.
		if (fadeOutComplete){
			fadeOutComplete = false;
			fadeAmount = 0;
			controlLockout = false;
			if (!fadeOnly){
				if (stateID == 10){
					gc.exit();
				}else{
					Game.setCS(stateID);
					sbg.enterState(stateID);
				}
			}
			fadeOnly = false;
		}
	}
	
	public void render(Graphics g){
		int displayWidth = Game.getInterfaceWidth();
		int displayHeight = Game.getInterfaceHeight();
		g.setColor(fade);
		g.fillRect(-16,-16,displayWidth+32,displayHeight+32);
		if (fade.a >= 1.0)
			font.drawStringCentered(displayWidth/2,displayHeight/2, "Loading", 0, 255, 0, 3);
	}
	
	public boolean getControlLockout(){return controlLockout;}
	public boolean getFadeOutCheck(){return fadeOutCheck;}
	
	public static TransitionModule getState(){return stateInstance.get(Game.getCS());}
	public static void removeState(){stateInstance.remove(Game.getCS());}
}

To clarify though, this is totally not the accepted practice. I just have not written a proper resource loader yet. But I use this class’s startTransition() to flip between states, it’ll fade out, “freeze” on the loading screen and then once enter() finishes eject you into whatever state you requested. Note that this TransitionModule object must be loaded in every single state to function correctly.

If you have a low, low load time (less than 3-4 seconds) this method works great though, since a resource loader is a bit overkill if you can almost load everything on the fly and you just want a little message to popup so people don’t think the game is frozen.