[WORKED AROUND] SayAt woes...

Started by DoorKnobHandle, Thu 17/02/2011 19:54:51

Previous topic - Next topic

DoorKnobHandle

Hey there! I'm working on a little 640x400 game, the characters all have very much transparent space around them for various big animations (so that their anchor point doesn't change) so the normal character.Say function doesn't position the text very well anymore (ie. way too high). So I wrote a super simple custom extender function called character.SayEx which is supposed to take care of the matter, here's the code:

Code: ags

function SayEx ( this Character *, String text )
{
	this.SayAt ( this.x - 100, this.y - 148, 200, text );
}


(Lucas Arts style speech BTW!)

It's only about the horizontal positioning of the text. For some reason all text will appear all the way to the right side of the screen! I checked the value of this.x and it is 256 (in a 640x400 room), so I don't see any reason why it would do that apart from being bugged.

What I'm trying to do is have the speech be displayed centered over the character like it would be when just calling character.Say but at a custom defined height (this.y - 148 in my case). So I pass the center coordinate of the player (this.x) - 100 as the boundary and a width of 200 (effectively this.x + 100) as the right one.

There are lots of other reported issues with the SayAt function, is it really bugged or documented improperly or am I doing something wrong? Any insight is appreciated!

Ryan Timothy B

#1
Remember that SayAt is based on screen coordinates not room coordinates. So if the character is off to the right side of a scrolling room, it'll appear to the right of the screen because your telling it to display beyond the 640 width. If the coordinates would have the speech box off screen, it will stop it at the very edge of the screen, never having the text 'off-screen'.

So you'll need:
Code: ags

function SayEx ( this Character *, String text )
{
	this.SayAt ( this.x - GetViewportX() - 100, this.y - GetViewportY() - 148, 200, text );
}


You don't necessarily need the GetViewportY, unless you actually have vertically scrolling rooms.

Edit: Reworded it to better explain how it's screen coordinates not room coordinates.


QuoteI checked the value of this.x and it is 256 (in a 640x400 room), so I don't see any reason why it would do that apart from being bugged.
Actually this part is starting to confuse me. If you actually meant 640x400 room and resolution, the only other issue I can see it being (if it's not due to being a scrolling room) would be the use low-resolution co-ordinates in script.

DoorKnobHandle

That is correct however my room isn't scrolling so missing the ViewportX/Y isn't the problem at hand. GetViewportX ( ) returns 0 in a 640x400 room in a 640x400 game. :

Ryan Timothy B

I edited my post shortly after you posted. :P

Is there any chance you have use low-resolution co-ordinates in script set as true? But I'm pretty sure the characters X would also be in low res, right? So the 264 should still be correct.

Do you have any 2x> filters being used? It's possible it's an unnoticed issue with the SayAt.

Khris

It's indeed pretty screwed up, not due to a wrong setting, as far as I can see.

You can improve things at least a bit though:

Code: ags
#define width 200
#define yspace 148

void SayEx(this Character*, String text) {
  int x = this.x - (width/2);
  if (x < 0) x = 0;
  if (x > System.ViewportWidth - width) x = System.ViewportWidth - width;
  int y = this.y - yspace;
  if (y < 0) y = 0;
  this.SayAt(x, y, 200, text);
}


It seems to be impossible to get SayAt to put text higher than [top of text's y] = 100.
You can avoid the other strange effects by making sure that the coordinates aren't out of range.

DoorKnobHandle

#5
@Ryan: Ah got ya. Well, use low-res coordinates in script is set to false and has been. I was using x2 (to effectively plat at 1280x800) but I just tried it at x1 and the problem remains unchanged.

@Khris: Unfortunately the problem's still there even with your code. I'll switch back to the Say function and see if that even aligns horizontally (I was pretty much only concerned with vertical positioning when I still used the Say function). If say doesn't align horizontally in a proper way something else must be broken (my character sprites are all centered of course :p ).

EDIT: Ok, sorry for the confusion. I just noticed that even the standard character.Say function displays text all the way on the right. Any ideas what could be causing this? My player character in the beginning is set to use a giant sprite because of a big animation, but it is then changed to a standard stand/walk view. Maybe the size isn't updated properly. I'll investigate.

To clarify, my character view has the standard 8 loops of 256x256 sprites with the player character centered. It also has a ninth loop that is almost fullscreen for a special animation. I was thinking it maybe got the size (and thus the player.x coordinate) off of the ninth loop maybe but then again when I check the player character position via debug mode and ctrl+d I get the exact right location from the output, ie character position x @ 256 which is exactly where its feet are drawn in the game. I'm throughly confused.

Khris

Say and SayAt shouldn't care about the width of the player's sprite, only about the player's position, at least in theory.

I tested my function by having it call SayAt(mouse.x, mouse.y, String.Format("%d, %d", mouse.x, mouse.y)), that way you can quickly check the behavior.

Calin Leafshade

Perhaps you should override the functionality completely with a gui label. It's only about 15 lines of code.

The SayAt function has always been a little screwy

DoorKnobHandle

#8
Yeah, looks like there isn't any way around completely bypassing all of AGS's speech functionality. This is the function I came up with, not exactly very nice code but it works fine so far:

Code: ags

function SayEx ( this Character *, String text )
{
	if ( text.CompareTo ( "..." ) == 0 )
	{
		Wait ( GetGameSpeed ( ) );
		return;
	}
		
	SpeechLabel.Text = text;
	SpeechLabel.TextColor = this.SpeechColor;
	
	int x = this.x - gSpeech.Width / 2;
	
	x -= GetViewportX ( );
	
	if ( x < 0 )
		x = 0;
	else if ( x > System.ScreenWidth - gSpeech.Width )
		x = System.ScreenWidth - gSpeech.Width;
	
	gSpeech.X = x;
	
	int y = this.y - FloatToInt ( 145.0 * ( IntToFloat ( this.Scaling ) / 100.0 ) );
	
	y -= GetTextHeight ( text, Game.SpeechFont, gSpeech.Width );
	
	y -= GetViewportY ( );
	
	if ( y < 0 )
		y = 0;
	else if ( y > System.ScreenHeight - gSpeech.Height )
		x = System.ScreenHeight - gSpeech.Height;
	
	gSpeech.Y = y;
	
	gSpeech.Visible = true;
	
	int old_view = this.View;
	
	this.LockView ( this.SpeechView );
	this.Animate ( this.Loop, this.SpeechAnimationDelay, eRepeat, eNoBlock );
	
	int timer = 0;
	
	while ( timer < GetGameSpeed ( ) * 2 && !mouse.IsButtonDown ( eMouseLeft ) && !IsKeyPressed ( eKeyEscape ) )
	{
		Wait ( 1 );
		timer++;
	}
	
	this.UnlockView ( );
	
	gSpeech.Visible = false;
}


It takes scaling, character colors, scrolling rooms and multi-line speech into account as well as animation, manual skipping with the left mouse button or escape and even the ellipsis that translates into a 1 second delay and no text output. All you need is make a transparent GUI called gSpeech with a label SpeechLabel on it.

For some reason it won't work in dialogs however (I'm using the "  player.SayEx ()" thingie in my dialogs). Any ideas why that would be?

Thanks for the help so far!

Calin Leafshade

Instead of using a wait command just set the speech font to an invisible font and then use c.Say for the click handling logic.

Saves rewriting everything.

DoorKnobHandle

#10
Ah yeah makes sense. Now I just need an invisible font. :p

EDIT: got one, thanks! For others: http://www.angelfire.com/pr/pgpf/if.html

Calin Leafshade

Radient's FontEdit is your friend.

Shane 'ProgZmax' Stevens

An approach I use expressly for SayAt is to keep a reserve blank character and just change the speech color to the character I want to 'use' and then use it to display the text where I want.  This avoids the sometimes weird offsets you encounter with it entirely and is relatively quick and worry free.

Ryan Timothy B

I find it odd that some of you have issues with the SayAt command because when I tested it and walked around random sized rooms, it seemed to work perfectly fine (unless the xy coordinates are displaying it off the top of the screen, it'll sometimes do random things). Is that the problems you all are having?

I still have no idea why dkh had his SayAt appearing to the right of the screen because when I used his exact code and had no issues. Perhaps game resolution has something to do with it. But then he said it was also doing it with the normal Say function. So you're thinking it's the character's size?

SMF spam blocked by CleanTalk