Trying to get a zelda style textbox going

Started by
9 comments, last by ISDCaptain01 10 years ago

Im trying to get Zelda style textbox going where it draws letter by letter, but Im having trouble doing this as nothing appears on my screen. Here is my function:


void drawtext2 (char text[], int x, int y)
{
	//Help delay writing the text
	int timecounter = 0;
	int delay = 100;

	//Counter
	int i;

	//Store letters in here
	char s[2] = {0,0};

	//Helps in the placing of each letter
	int px = x;

	//Now lets start drawing each letter
	for(i = 0; i < strlen(text); i++)
	{
		//First Grab a letter from the text array 
		s[0] = text[i];

		//Now lets draw it
		//Check to see if the timecounter has surpassed the delay counter
		if(++timecounter > delay)
		{
			//Now draw the letter
			al_draw_text(font, al_map_rgb(255, 255, 255), px, y, NULL, s);
			//Play the beep for the letter draw
			al_play_sample_instance(beepInstance);
			cout << s[0] << endl;

			//Increment some space for the next letter
			px += al_get_text_width(font, s);

			//After all that, reset the counter
			timecounter = 0;
		}
	}

	
}
Advertisement

The timecounter variable is created and set to 0 every time the function is called.

I'm thinking unless you pass in a text string which is at least 100 characters long, nothing will ever display.

Setting it to static might work, but you don't want to increment it within the for loop. You want to increment it before the for loop occurs.

Imagine delay was = 3. Updating timecounter inside the for loop would make every 4th character be written.

(char0, timecounter = 1, char1, timecounter = 2, char2, timecounter = 3, char3, timecounter = 4 --> greater than delay, print char3)

An alternative to setting timecounter to static would be to calculate the amount of characters to print outside of the drawtext2 function and pass it through as a new parameter to drawtext2, e.g. as int numCharsToPrint.

In either case (static or gotten from from parameter), the for loop would then just loop through (for int i = 0; i < numCharsToPrint; i++) //print;

Do you really intend to print the character + a newline using cout? I'm guessing this is for debugging purposes.

I don't see a reason for declaring int i outside of the for loop.

A lot of games have it so the text prints more quickly if a specific button is held down. You could do this by not resetting timecounter everytime you print.

You'd then do something like...

timecounter += buttonPressed ? 50 : 1;

if (timecounter > (delay * i + 1))

Sorry if the post is somewhat jumbled, quite tired.

Hello to all my stalkers.

But I don't get it, what does timecounter and delay have to do with the printing of the characters. They are only there to slow the printing down.

void drawtext2 (char text[], int x, int y)
Well first off how are you actually getting time in here? I don't see you passing a delta time.

//Help delay writing the text
int timecounter = 0;
int delay = 100;
As was stated above this information gets reset every time you enter the function, so unless you are going to draw the entire message box text instantly inside the function, it would be impossible.

Reading ahead I really don't get what you're trying to do, were you expecting to make the loop sit there and delay for seconds while nothing else in the game is working? That won't work.

To actually draw a scrolling text box you'd have to have a buffer with the text in it and every drawing frame of the game, you simply draw what is already in the buffer. During your update you should be passing the delta time that has passed and make that add more letters(based on how much time has passed) you can have your update play the beep sound with each letter as well.

//Counter
int i;
Why is this defined here? You clearly define it in the for loop so this one just gets shadowed. There's no real reason for it to be outside the loop anyway.

Random side note: please don't ever name variables like this unless they're controls in a loop, it just makes it really unclear what they do.
//Store letters in here
char s[2] = {0,0};

//Helps in the placing of each letter
int px = x;
Now for this beast.
//Now lets start drawing each letter
for(i = 0; i < strlen(text); i++)
{
	//First Grab a letter from the text array 
	s[0] = text[i];

	//Now lets draw it
	//Check to see if the timecounter has surpassed the delay counter
	if(++timecounter > delay)
	{
		//Now draw the letter
		al_draw_text(font, al_map_rgb(255, 255, 255), px, y, NULL, s);
		//Play the beep for the letter draw
		al_play_sample_instance(beepInstance);
		cout << s[0] << endl;

		//Increment some space for the next letter
		px += al_get_text_width(font, s);

			//After all that, reset the counter
			timecounter = 0;
		}
	}	
}
To me it looks like each iteration of this loop you are just incrementing timecounter by 1 and it will only draw a letter if you have more than 100 iterations of it. If this was supposed to be time keeping I don't get what you were trying to do with it. This basically doesn't do anything because unless your text is over 100 characters it will just loop n times and then exit the function without ever having drawn anything.

Well I think Im heading in the right place, its still funky but I came up with this:

What happens now is that the text does slowly print according to each second passed, but each letter moves off the screen way too fast


void DrawScrollText(char text[], int &x, int &y)
{
	timeElapsed = al_get_time() - tickCounter;
	storage[0] = text[timeElapsed];

	if(timeElapsed < strlen(text))
	{
		al_draw_text(font, al_map_rgb(255, 255, 255), 
		         x += al_get_text_width(font, storage), y, NULL, storage);
		al_play_sample_instance(beepInstance);
	}
	else
		return;
}

I would appreciate more feedback, I want to get this working

Are you basing this code off something else? You're repeating some earlier mistakes we've already pointed out, which leads me to think you don't fully understand what you're posting here.
Notably: You're still doing stuff where you declare & define a variable at the start (assumption: assigned to same value), and seem surprised that the position is the same throughout.
I'll be guessing a bit here, based on your description of what happens.
1. You're calling this function every update, with the same input every time (full text string you want to be printed sequentially, positionX and positionY). I'm assuming this because you say the behavior/output changes. Keep doing this. Note that I'm assuming this despite you not mentioning whether or not the sound plays correctly. I am guessing the sound plays repeatedly, far too frequently.
2. When you're testing this, you are starting the text drawing at startup. I'm assuming this based on guessing that al_get_time() returns seconds since the application was started, and because you say the text prints each individual letter from start to finish. This will hide a future problem, but I'll get to that.
3. px is supposed to be the current character's x position, while the int x parameter is the start x position.
Things that go wrong with your approach:
1. You only every print one character.
2. You play a sound every time you call the function.
3. You never advance the text cursor -- you always print in the same location. This is linked to only printing one character every time you call the function.
4. The timer you're using will only work immediately upon starting the game.
5. If left running, text[timeElapsed] will try to access garbage data (timeElapsed will surpass the number of characters in the text string).
Things you need to do:
1. Figure out how many characters to print. This involves being able to tell how much time has passed from when the text printing began. This also involves never trying to print more characters than are in the given text string.
2. Print the correct amount of characters, using the information above.
3. Figure out a way to tell if you should play a sound (this could be based on time, or based on more characters printed now than previous function call, or something else).
I'm slightly hesitant in terms of just posting a suggested solution (and honestly, somewhat tired again!). I'd suggest trying to solve the issues above on your own, and posting again if you run into problems, or if you've just got questions.
Hopefully that helps, both in accomplishing your goals and possibly increasing your programming abilities smile.png
Also, as a minor note to Satharis: int i is actually not redeclared/ghosted in the for loop. The for loop just uses the already declared i. As I mentioned in my first post, though, there is no reason to declare the variable before the loop in this case.
---
EDIT: I typed all of this up before your edit. Most of the issues I listed are still relevant.

Hello to all my stalkers.

Well this is what Im doing now: Here is the function to write the scrolling text box:


//Scrolling text box function
void DrawScrollText(char text[], int &x, int y)
{
        //Record the previous elapsed time
	oldTime = timeElapsed;

        //Get the current time minus the tickcounter from the game
	timeElapsed = al_get_time() - tickCounter;

        //Store a letter from the text array
	storage[0] = text[timeElapsed];
	
        //Bounds checking, don't write more than whats in the text array
	if(timeElapsed < strlen(text))
	{
                //Draw the text
		al_draw_text(font, al_map_rgb(255, 255, 255), 
		         x += 1 /*al_get_text_width(font, storage)*/, y, NULL, storage);
                
                //If the time elapsed has changed than make a beep
		if(timeElapsed != oldTime)
			al_play_sample_instance(beepInstance);
	}

        //Else don't do anything
	else
	{
		return;
	}
}

Than I have this function where I pass my current position in the text array and print it permanently onto the screen:


void CharsToPrint(int elapsedTime, char text[], int x, int y)
{
	for(int i = 0; i < elapsedTime; i++)
	{
		s[0] = text[elapsedTime];
		al_draw_text(font, al_map_rgb(255, 255, 255), x, y, NULL, s);
		x+=1;
	}
}

The problem Im facing is that the cursor flies right off the screen and the letters don't permantly stay after being printed.

Man this is harder than I thought lol.

I don't want to be rude but when I'm reading your code I get feeling that you don't understand some basic concepts and that you don't understand what you are doing.

Your problem with printing text letter by letter i would solve like:

For index=0 <= number of letters in array

{

Print array[index]

Increment index

pause for like 200 or 300 ms

}

How to implement this concept is up to you, no one here will give you solution on plate.

You ask for feedback from us but you don't give any back. Guys told you some advices but you didn't take them seriously and you repeat same mistakes.

For your second question i won't even reply because it is obviously copy paste of someone else.

I don't want to be rude but when I'm reading your code I get feeling that you don't understand some basic concepts and that you don't understand what you are doing.

Your problem with printing text letter by letter i would solve like:
For index=0 <= number of letters in array
{
Print array[index]
Increment index
pause for like 200 or 300 ms
}

How to implement this concept is up to you, no one here will give you solution on plate.
You ask for feedback from us but you don't give any back. Guys told you some advices but you didn't take them seriously and you repeat same mistakes.
For your second question i won't even reply because it is obviously copy paste of someone else.


I think your being too harsh. Im still learning and by no means am a professional. Im reading the posts and modifying my code. I got the sound to beep now only when the tkme chnages rather than continously. I fixed the bounds checking as well. Im now working on a solution to pass the letters processed to a function to print them permanantly. Im taking every feedback seriously or would not have made it this far in gamedev itself

You can try simple division. Prepare the full string you want to show, and show N characters from that string,

where N = floor( time_since_creation_of_textbox / delay_per_character )

This topic is closed to new replies.

Advertisement