This is what a running text look like. The term itself could mean anything else, so I decided to put a GIF here for context.
And this is what I'm currently doing, using the code given below:
I have created an inflexible running text code. It's not only bloated with variables, but also this is the only way I could think up of for the past few hours. But, it runs very fine. And now I want to optimize it.
private String[] tokens;
private int tokenPointer;
private int beginningPointer;
private int firstLinePointer;
private int secondLinePointer;
private int totalStringPointer;
private boolean firstLineFull;
private boolean secondLineFull;
private Map<Integer, Boolean> dialogs;
private boolean next;
private boolean nextTick;
private int stringPointer;
private byte tickSpeed;
private byte arrowTickSpeed;
private String dialogueText;
private boolean showDialog;
public void renderTextGraphics(Graphics g) {
if (this.dialogueText != null && !this.dialogueText.isEmpty()) {
//The game uses 8f FONT when shown on the screen. It is scaled by GAME_SCALE.
//Text are drawn with positive X = RIGHT, positive Y = UP. Not the other way around.
g.setColor(Color.black);
g.setFont(Art.font.deriveFont(Font.PLAIN, 24f));
if (this.totalStringPointer <= this.dialogueText.length()) {
//Handles one word sentences only.
if (this.stringPointer > this.dialogueText.length()) {
this.stringPointer = this.dialogueText.length();
this.next = true;
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.stringPointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
return;
}
if (this.totalStringPointer == this.dialogueText.length()) {
this.next = true;
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.firstLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
g.drawString(this.dialogueText.substring(this.beginningPointer + this.firstLinePointer, this.dialogueText.length()), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextSecondLineStartingY());
return;
}
if (this.firstLineFull && this.secondLineFull) {
this.next = true;
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.firstLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
g.drawString(this.dialogueText.substring(this.beginningPointer + this.firstLinePointer, this.beginningPointer + this.secondLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextSecondLineStartingY());
return;
}
//Handles more than one word.
String text = this.tokens[this.tokenPointer];
if (this.firstLinePointer + text.length() <= MAX_STRING_LENGTH) {
if (this.stringPointer > text.length()) {
this.firstLinePointer += this.stringPointer;
this.secondLinePointer = this.firstLinePointer;
if (this.tokenPointer < this.tokens.length - 1) {
this.tokenPointer++;
this.stringPointer = 0;
}
//Short sentences.
if (this.totalStringPointer >= this.dialogueText.length() - 1) {
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.firstLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
return;
}
}
}
else {
this.firstLineFull = true;
}
if (this.firstLineFull) {
if (this.secondLinePointer + text.length() < MAX_STRING_LENGTH * 2) {
if (this.stringPointer > text.length()) {
this.secondLinePointer += this.stringPointer;
if (this.tokenPointer < this.tokens.length - 1) {
this.tokenPointer++;
this.stringPointer = 0;
}
}
}
else {
this.secondLineFull = true;
}
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.firstLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
if (!this.secondLineFull) {
if (this.secondLinePointer + text.length() < MAX_STRING_LENGTH * 2) {
g.drawString(this.dialogueText.substring(this.beginningPointer + this.firstLinePointer, this.beginningPointer + this.secondLinePointer + this.stringPointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextSecondLineStartingY());
}
}
else {
g.drawString(this.dialogueText.substring(this.beginningPointer + this.firstLinePointer, this.beginningPointer + this.secondLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextSecondLineStartingY());
this.next = true;
}
}
else {
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.firstLinePointer + this.stringPointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
}
}
else {
this.next = true;
g.drawString(this.dialogueText.substring(this.beginningPointer, this.beginningPointer + this.firstLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextStartingY());
g.drawString(this.dialogueText.substring(this.beginningPointer + this.firstLinePointer, this.beginningPointer + this.secondLinePointer), Dialogue.getDialogueTextStartingX(), Dialogue.getDialogueTextSecondLineStartingY());
return;
}
}
}
For the background context: The problem for me is the way the running text works.
For each game update ticks, it draws a new letter at the end of the string. Once it reaches the end of the dialog box, it should automatically move itself to the next line. In order to accomplish this, I need to use three pointers. One for keeping track of the beginning of a string, because the area of the dialog box is limited, and dialogues are rarely just 2 lines at the most. The other two pointers keep track of each line, checking to make sure the text are staying in bounds of the dialog box.
When the text is more than 1 dialog box big, I swap the ones keeping track of the beginning of a sentence and the end of the sentence, so the beginning is now 1 sentence ahead, and erase the end of the old sentence so that it can keep track of the new sentence.
I thought using 3 variables is enough for me, but it turns out I need like 10 of them just to get the auto-newline part implemented.
--------------------------------------------------
I don't know how to optimize it more as I have been thinking alone on this part. Could anyone provide tips on how I should "optimize" the codes a bit? Thanks in advance.
EDIT: Apparently, there are still bugs in that portion of code. I am really thinking I'm not implementing the running text as well as I thought. Ugh!