0
\$\begingroup\$

I'm trying to make a textbox for a small game and I've run into an issue. I'm using drawString, which doesn't support \n so I've made an array of strings for multiple lines like so. Also, there is a global int called lettersShown that will be important later.

int lettersShown = 0;
String[] result = new String[] {" "," "," "," "," "," "," "," "};

In the constructor of the class, I then created a random event containing an array of 8 strings(Sorry if this is long and poorly formatted, its just for testing purposes.)

travel.add(new Event(this, new String[]{"You walk along a winding dirt 
road,", "exposed to the scorching of the sun.",
            "Every so often, you pass the remains", "of blasted homes 
and dilapidated", "hovels. The air is especially arid", 
            "today, and by the time the sun drifts", "down into the horizon 
you find", "yourself parched."}, -20,0,0,0));

So after I did that, I created a method to draw each line in order.

public void drawText( int x, int y, Graphics g) {   

    for(int i = 0; i <result.length; i++) {
        g.drawString(result[i].substring(0, lettersShown), x, y);
        if(result[i].length() > lettersShown) {
            lettersShown++; 
    }
        //lettersShown = 0;
        y+=15;

    }
}

This method works perfectly for any arrays that only have one string, such as this one:

travel.add(new Event(this, new String[] {"You traveled to a new city"}, 
0,0,0,0));

However, the second it starts to render an event with multiple lines, I get this exception

Exception in thread "Thread-1" 
java.lang.StringIndexOutOfBoundsException: String index out of range:23
at java.lang.String.substring(String.java:1963)
at mains.EventManager.drawText(EventManager.java:149)
at mains.Game.render(Game.java:185)
at mains.Game.run(Game.java:87)
at java.lang.Thread.run(Thread.java:748)

I've been trying so many things to fix this seemingly small issue and I'd rather not resort to just having a ton of strings and drawing each of them one at a time so any guidance or anyone who can identify the problem would be greatly appreciated. Thanks!

\$\endgroup\$
  • 1
    \$\begingroup\$ Next, try this one: If you wanted to display the strings "Hello" "You", what substring of "You" would you try to form when lettersShown = 4? \$\endgroup\$ – DMGregory May 3 '18 at 13:21
  • \$\begingroup\$ Letters shown would never reach 4 because "You" only has three characters. Is lettersShown one more than its supposed to be? \$\endgroup\$ – Christopher Sheehy May 3 '18 at 14:17
  • \$\begingroup\$ Where are you setting lettersShown back to 0? \$\endgroup\$ – Niall Quinlan May 3 '18 at 14:32
  • \$\begingroup\$ These strings are supposed to appear when you press one of four buttons so when you press the buttons, the lettersShown is reset to 0. \$\endgroup\$ – Christopher Sheehy May 3 '18 at 14:38
  • \$\begingroup\$ Heres an example . public String[] scavenge() { lettersShown=0; int rand = (int)(Math.random()*5); if(sustenance < 50) { rand = (int)(Math.random()*scavenge.size()); } result = scavenge.get(rand).getResult(); scavenge.get(rand).eventEffect(); sustenance-=5; exhaustion+=5; carryOver = 5 - (24-hours); hours+=5; return result; } \$\endgroup\$ – Christopher Sheehy May 3 '18 at 14:38
1
\$\begingroup\$

Let's walk through this method one step at a time:

public void drawText( int x, int y, Graphics g) {   

    for(int i = 0; i <result.length; i++) {
        g.drawString(result[i].substring(0, lettersShown), x, y);
        if(result[i].length() > lettersShown) {
            lettersShown++; 
    }
        //lettersShown = 0;
        y+=15;

    }
}

Say result = ["Hello", "You"] and we're at lettersShown = 3, i = 0:

  1. g.drawString(result[i].substring(0, lettersShown), x, y);

    will print "Hello".substring(0, 3), ie. "Hel" - so far so good.

  2. if(result[i].length() > lettersShown)

    well, "Hello" has length 5 > 3, so this test passes.

  3. lettersShown++; So now lettersShown = 4

  4. } We hit the end of our loop, so we increment i to 1 and start again.

  5. g.drawString(result[i].substring(0, lettersShown), x, y);

    will try to print the first lettersShown = 4 letters of result[1] = "You"... uh oh.

    "You" has only 3 letters, but we're trying to get a substring of length 4 out of it! Kaboom.

So: you need to keep track of how many letters of the current string you want to print.

public void drawText( int x, int y, Graphics g) {
    // Let's show one more letter than we did last time.
    lettersShown++;

    int lettersRemaining = lettersShown;

    for(int i = 0; i <result.length && lettersRemaining > 0; i++) {

        // Don't try to take more letters than we have!
        int substringLength = Math.min(lettersRemaining, result[i].length());

        g.drawString(result[i].substring(0, substringLength), x, y);

        // Proceed to next line
        // Update our remaining letter count & vertical position.
        lettersRemaining -= result[i].length();        
        y+=15;    
    }
}
\$\endgroup\$
  • \$\begingroup\$ Great, I just saw this, tried to do something similar to it and it ended up working. Thank you so much for the patience and advice. \$\endgroup\$ – Christopher Sheehy May 3 '18 at 18:45
  • 1
    \$\begingroup\$ Don't forget to hit the Accept checkmark to mark the issue as resolved. \$\endgroup\$ – DMGregory May 3 '18 at 19:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.