tzachshabtay / MonoAGS

AGS (Adventure Game Studio) reimagined in Mono
https://tzachshabtay.github.io/MonoAGS/
Artistic License 2.0
27 stars 8 forks source link

Add option to give specific text position to "Say" #299

Closed tzachshabtay closed 6 years ago

tzachshabtay commented 6 years ago

This is the equivalent to "SayAt" in AGS, you can now override the text position by doing: "await cEgo.SayAsync("Hello!", (100, 50));"

You can also override the portrait position (if there's a configured portrait): "await cEgo.SayAsync("Hello!", portraitPosition: (100, 50));"

ghost commented 6 years ago

I realize you are probably adding this to make it easier for newcomers, but imho this again assumes particular speech style and "portrait" entity in the engine API (something that we've discussed a while ago). Idk what's your plans are, but just wanted to note this.

tzachshabtay commented 6 years ago

I don't have any particular plans for it. I'm currently content with the compromise of having a built-in "portrait" entity in the API as I know this is very common in adventure games, and those games that don't need a portrait can simply ignore it. I'm happy to discuss alternative APIs though that still allow for easy plug & play portraits, though, if you have any ideas.

Other than the portrait issue, my only assumption on speech style here that I can see is that there's text that needs to be displayed somewhere on the screen, and I don't see an issue with it?

ghost commented 6 years ago

Yes, I realize this may be kind of too much abstraction in what I am talking about. I was wondering though if there could be some kind of "middle-level" solution to this. I.e., if we are importing a template library that implements a speech style, or group of speech styles based on displaying text w/wo portrait, then it may also provide additional scripting functions to deal with positioning.

Regarding actual implementation, the only thought that comes at the moment is this: if there were the way to get the "object" that controls looks of the speech on screen (not sure what it is at the moment), either as return value of Say, or in any other reliable way, then one could write an extension method, e.g. (pseudo code):

Task SayAt(this Character, string text, PointF textPositionl, PointF portraitPosition)
{
    Task task = this.Say(text);
    var sayLocation = ... get somehow.
    sayLocation.TextPosition = textPosition;
    sayLocation.PortraitPosition = portraitPosition;
    return task;
}

I'm happy to discuss alternative APIs though that still allow for easy plug & play portraits, though, if you have any ideas.

Unfortunately, I did not research how Say implementation works in the engine yet, so no, I cannot suggest anything regarding API.

tzachshabtay commented 6 years ago

There is a way to get that "object" using the "OnBeforeSay" event, so one could have written an extension method:


Action<BeforeSayEventArgs> setPosition = args => 
{
   args.Label.Position = textPosition;
   character.SpeechConfig.PortaitConfig.Portrait.Position = portraitPosition;
};
character.OnBeforeSay.Subscribe(setPosition);
await character.SayAsync("Hello");
character.OnBeforeSay.Unsubscribe(setPosition);

But this is not as pretty as built-in support, and also in case a character says several things at the same time where you want different positions it will get even uglier.

ghost commented 6 years ago

Hmmm, no, this certainly does not look like a good thing...

Oh, it also has PortraitConfig right in character.

Well, nevemind then, guess more abstraction won't work here, at least not atm.