Simple Slick Textbox engine just incase..

I had some problems with Unicode where the text wouldn’t draw, even after all the necessary setup protocols. AngelCodeFont was a bit of overkill, and the indexes in TrueTypeFont weren’t working for whatever reason. So I wrote this, I felt it’d be right to share it, in case someone else needed it too.

package edu.bgp.global.utilities;

import java.awt.Font;
import java.util.List;
import java.util.ArrayList;

import org.newdawn.slick.Image;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.Color;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Input;
import org.newdawn.slick.GameContainer;

/**
 * 
 * @author Brayden McKinney
 * Written on 1/10/12
 *
 *If you use this, you don't have to give credit. Modify as you please, but if you do, share it.
 *I made this, because Slicks normal font rendering code wasn't working properly. This tries to simplify
 *text rendering in RPG games and the like.
 *
 */

public class textBoxBase{
	TrueTypeFont trueTypeFont;
	Image textBox;
	Image textDown;
	
	int line = 0; //Line being rendered. Draws 3 of theses when rendered. So increment accordingly.
	int size = 0; //The amount of lines to draw. 
	int cooldown = 0; //Cooldown of the clicker, so text doesn't scroll too fast.
	static final int COOLDOWNSET = 20; //Amount of time I wait for my cooldown.
	
	float boxFader = 0;
	int boxSlider = 160;
	int textFader = 0;
	
	public boolean rendering = false;
	
	String textToRender[]; //Text spliced and ready.
	String personTalking = ""; //Person talking. 
	List <String> textQueue = new ArrayList<String>(); //Text waiting for render.
	List <String> nameQueue = new ArrayList<String>(); //Name queue. 
	
	public textBoxBase(){
		try{
			trueTypeFont = new TrueTypeFont(new Font("Arial", Font.ITALIC, 16), true);
			textBox = new Image("res/gui/textBox.png");
			textDown = new Image("res/gui/textDown.png");
		}catch(SlickException e){}
	}
	
	//Render code, place in the loop of the game if you want the textbox in that part of the engine.
	public void render(Graphics g, GameContainer gc){
		Input input = gc.getInput();
		
		//Draw boxes and it's parts.
		g.drawImage(textBox, 90, 360+boxSlider, new Color(1f,1f,1f,boxFader));
		
		if (cooldown == 0){
			g.drawImage(textDown, 650, 500+boxSlider,new Color(1f,1f,1f,boxFader));
		}
		
		if (rendering){
			//Faders to make it more smexy.
			if (boxFader < 1){
				boxFader += 0.10;
				boxSlider -= 15;
			}
			
			if (textFader != 255){
				textFader += 15;
			}
			
			try{
				trueTypeFont.drawString(170, 410, personTalking, Color.black);
				trueTypeFont.drawString(200, 430, textToRender[line] , new Color(0, 0, 0, textFader));
				trueTypeFont.drawString(200, 450, textToRender[line+1] , new Color(0, 0, 0, textFader));
				trueTypeFont.drawString(200, 470, textToRender[line+2] , new Color(0, 0, 0, textFader));
			}catch(Exception e){}
		
			if (input.isMouseButtonDown(input.MOUSE_LEFT_BUTTON)){
				//Scroll text.
				if (line <= size && cooldown == 0){line+=3; cooldown = COOLDOWNSET; textFader = 0;}
			}
			
			//If lines are at the length, shut down text rendering.
			if (line > size){
				rendering = false;
			}
			
			//Cooldown.
			if (cooldown != 0){cooldown--;}
		}
		
		if (!rendering){
			line = 0;
			
			//Check text queue. Move on to next text if so, if not, it shuts the text box down.
			if (!textQueue.isEmpty()){
				spliceText(textQueue.get(0), nameQueue.get(0));
				textQueue.remove(0);
				nameQueue.remove(0);
			}else{
				if (boxFader != 0){
					boxFader -= 0.30;
					boxSlider+=40;
				}
			}
			
			textFader = 0;
		}
	}
	
	//Read and cut text where neccesary, then place it in the array; then tell the render to 
	//render the text. It also assigns the name of the person talking.
	public void spliceText(String text, String name){
		int mark = 0;
		personTalking = name;
		textToRender = new String[text.length()/50+4];
		size = text.length()/50;
        for (int x = 0; x < text.length(); x++){
        	if (x > mark+50){
        		textToRender[mark/50] = text.substring(mark, x);
        		textToRender[(mark/50)+1] = "";
        		textToRender[(mark/50)+2] = "";
        		mark = x;
        	}else{
        		if (mark+50 > text.length()){
        			textToRender[mark/50] = text.substring(mark, text.length());
        		}
        	}
        }
        rendering = true;
	}
	
	//Send messages you want rendered, if one is already being rendered, text is added to a queue.
	//It also adds names of the person talking the same way.
	public void newMessage(String text, String name){
		if (rendering == false){
			spliceText(text, name);
		}else if (rendering){
			textQueue.add(text);
			nameQueue.add(name);
		}
	}
}

I uploaded the older version so people could optimize the code in their own preferred ways (Yes, I know it’s not fully optimized. lol).

Also, if you do modify it, please place it in this thread. It needs an auto spacer (So words are full of each line), which I haven’t even implemented into my own yet, so if you make one please do share.

This is a more optimized version, it also can space the text right so you don’t have to manually.

Here’s the code, it’s not commented, but if you read the comments in the older version, you’ll be able to understand it and the changes just fine. Honestly, this is mainly for the newcomers to java. I’m not saying I’m awesome or anything, but I know when I was new at programming, code like this made me jump for joy.

package edu.bgp.global.utilities;

import java.awt.Font;
import java.util.List;
import java.util.ArrayList;

import org.newdawn.slick.Image;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.TrueTypeFont;
import org.newdawn.slick.Color;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.Input;
import org.newdawn.slick.GameContainer;

/**
 * 
 * @author Brayden McKinney
 * Written on 1/10/12
 *
 *If you use this, you don't have to give credit. Modify as you please, but if you do, share it.
 *I made this, because Slicks normal font rendering code wasn't working properly. This tries to simplify
 *text rendering in RPG games and the like.
 *
 */

public class textBoxBase{
	TrueTypeFont trueTypeFont;
	Image textBox;
	Image textDown;
	
	int line = 0;
	int size = 0; 
	int cooldown = 0; 
	static final int COOLDOWNSET = 20;
	static final int TEXTBOXLENGTH = 40;
	
	float boxFader = 0;
	int boxSlider = 160;
	int textFader = 0;
	
	public boolean rendering = false;
	
	String textToRender[]; 
	String personTalking = ""; 
	List <String> textQueue = new ArrayList<String>();
	List <String> nameQueue = new ArrayList<String>(); 
	
	public textBoxBase(){
		try{
			trueTypeFont = new TrueTypeFont(new Font("Arial", Font.ITALIC, 16), true);
			textBox = new Image("res/gui/textBox.png");
			textDown = new Image("res/gui/textDown.png");
		}catch(SlickException e){}
	}
	
	public void render(Graphics g, GameContainer gc){
		Input input = gc.getInput();
		
		g.drawImage(textBox, 90, 360+boxSlider, new Color(1f,1f,1f,boxFader));
		
		if (cooldown == 0){
			g.drawImage(textDown, 650, 500+boxSlider,new Color(1f,1f,1f,boxFader));
		}
		
		if (rendering){
			if (boxFader < 1){
				boxFader += 0.10;
				boxSlider -= 15;
			}
			
			if (textFader != 255){
				textFader += 15;
			}
			
			try{
				trueTypeFont.drawString(170, 410, personTalking, Color.black);
				trueTypeFont.drawString(200, 430, textToRender[line] , new Color(0, 0, 0, textFader));
				trueTypeFont.drawString(200, 450, textToRender[line+1] , new Color(0, 0, 0, textFader));
				trueTypeFont.drawString(200, 470, textToRender[line+2] , new Color(0, 0, 0, textFader));
			}catch(Exception e){}
		
			if (input.isMouseButtonDown(input.MOUSE_LEFT_BUTTON)){
				if (line <= size && cooldown == 0){line+=3; cooldown = COOLDOWNSET; textFader = 0;}
			}
			
			if (line > size){
				rendering = false;
			}
			
			if (cooldown != 0){cooldown--;}
		}
		
		if (!rendering){
			line = 0;
			
			if (!textQueue.isEmpty()){
				spliceText(textQueue.get(0), nameQueue.get(0));
				textQueue.remove(0);
				nameQueue.remove(0);
			}else{
				if (boxFader != 0){
					boxFader -= 0.30;
					boxSlider+=40;
				}
			}
			
			textFader = 0;
		}
	}

	public void spliceText(String text, String name){
		int mark = 0;
		personTalking = name;
		
		size = text.length()/TEXTBOXLENGTH;
		textToRender = new String[size+10];
		
        for (int x = 0; x < text.length(); x++){
        	if (x > mark+TEXTBOXLENGTH){
        		int newMark = x;
        		
        		if (text.charAt(x) != ' ' && newMark == x){
        			for (int a = x; a < text.length(); a++){
        				if (text.charAt(a) == ' '){
        					newMark = a;
        					break;
        				}
        			}
        		}
        		
        		if (text.charAt(x) != ' ' && newMark == x){
        			for (int a = x; a > mark; a--){
        				if (text.charAt(a) == ' '){
        					newMark = a;
        					break;
        				}
        			}
        		}
        		
        		textToRender[mark/TEXTBOXLENGTH] = text.substring(mark, newMark);
        		textToRender[(mark/TEXTBOXLENGTH)+1] = "";
        		textToRender[(mark/TEXTBOXLENGTH)+2] = "";
        		
        		mark = newMark;	
        	}else{
        		if (mark+50 > text.length()){
        			textToRender[mark/TEXTBOXLENGTH] = text.substring(mark, text.length());
        		}
        	}
        }
        rendering = true;
	}
	
	public void newMessage(String text, String name){
		if (rendering == false){
			spliceText(text, name);
		}else if (rendering){
			textQueue.add(text);
			nameQueue.add(name);
		}
	}
}