Ideas on how to generate an outline on-the-fly?

Started by Monsieur OUXX, Fri 15/11/2013 22:38:24

Previous topic - Next topic

Monsieur OUXX

I'm considering ways of faking a font outline when a character speaks.
I was thinking of a solution that's not perfect but might do the trick : displaying 4 (or 8) times the text in black, with 1-pixel shift in every direction,, under the actual coloured text.

How would you do that?

I'm trying this :

1) I created a dummy character, cOutline1, with a transparent view (i.e. it can speak, but it has an invisible body)
2) Its speech color is bright green (for tests, to be sure I'll see it on my screen)
3) I tried the following script:
Code: ags

cOutline1.x = player.x; //test pixel offset
cOutline1.y = player.y-10; //test pixel offset
cOutline1.SayBackground(s);
player.Say(s);


Strangely, when I test, I don't see the .SayBackground sentence. I only see the .Say sentence.
What am I doing wrong?
 

Monsieur OUXX

#1
The script above was faulty in many ways, so here is a new version :



  //we force the speech animation
  c.StopMoving();
  c.LockView(c.SpeechView);
  c.Animate(c.Loop, 4, eRepeat , eNoBlock); //make sure this is non-blocking
 
 
  cOutline1.ChangeRoom(c.Room); //just to make sure they're in the same room
  cOutline1.x = c.x; //we position the fake outline
  cOutline1.y = c.y-10;
  Wait(1);
  cOutline1.Say("");  //so that if wait time is skipped, the character stops talking
  c.Say("");  //so that if wait time is skipped, the character stops talking


  cOutline1.SayBackground(s); //we make both the outline and the character say the same thing
  c.SayBackground(s); //we need to use saybackground here, because "say" interrupts the previous saybackground
  WaitMouseKey((s.Length/Game.TextReadingSpeed + 1) * GetGameSpeed()); //so wait time can be skipped
 
  cOutline1.Say("");  //so that if wait time is skipped, the character stops talking
  c.Say("");  //so that if wait time is skipped, the character stops talking
 
  c.UnlockView();
  Wait(1);




However there is still an issue :
When I click to interrupt the sentence, the character says the sentence AGAIN. But this time the sentence does not appear in the same place!?! (like 10 pixels lower). And if I click somewhere before he's finished talking, now he can walk while talking. Terrible.
 

Crimson Wizard

There's a way to control background speech overlay:

Code: ags

Overlay *o = cCharacter.SayBackground(...);
<...>
o.Remove();

Monsieur OUXX

Quote from: Crimson Wizard on Fri 15/11/2013 23:29:46
There's a way to control background speech overlay

Cool, that will come handy to make the outline look better.
But my main issue right now is sync'ing the speech view, and the appearance and disappearance of the real text and the outline (as explained in my second post)
 

Crimson Wizard

Quote from: Monsieur OUXX on Fri 15/11/2013 23:35:15
But my main issue right now is sync'ing the speech view, and the appearance and disappearance of the real text and the outline (as explained in my second post)
I mean, you can replace this
Code: ags

cOutline1.SayBackground(s); //we make both the outline and the character say the same thing
c.SayBackground(s); //we need to use saybackground here, because "say" interrupts the previous saybackground
<...>
cOutline1.Say("");  //so that if wait time is skipped, the character stops talking
c.Say("");  //so that if wait time is skipped, the character stops talking

with this:
Code: ags

Overlay *o1 = cOutline1.SayBackground(s); //we make both the outline and the character say the same thing
Overlay *o2 = c.SayBackground(s); //we need to use saybackground here, because "say" interrupts the previous saybackground
<...>
// Remove both overlays at once
o1.Remove();
o2.Remove();

Monsieur OUXX

Thanks Crimson. I've actually found the solution.

The difficulty (and the reaosn why your solution wouldn't work as-is -- that's also what I tried in the first place) was in the small prints of SayBackground. It's interrupted by any "Say" AND it doesn't animate the speech. that's a pain in the ass to use.

But everything is solved with  game.bgspeech_stay_on_display


  game.bgspeech_stay_on_display = 1; //to make sure that a "Say" won't discard a "SayBackground"
 
  cOutline1.ChangeRoom(c.Room); //just to make sure they're in the same room
  cOutline1.x = c.x; //we position the fake outline
  cOutline1.y = c.y-10;
  Wait(1);
 
  Overlay* o = cOutline1.SayBackground(s); 
  c.Say(s);  //by using "Say", we benefit of the animated character.

  if (o.Valid != 0)
    o.Remove(); //we remove the overlay so that the outline disappears at the same time as the actual text



Now it works perfectly.

 

Ghost

Quote from: Monsieur OUXX on Fri 15/11/2013 22:38:24
I was thinking of a solution that's not perfect but might do the trick : displaying 4 (or 8) times the text in black, with 1-pixel shift in every direction,, under the actual coloured text.

Maybe off-topic, but I remember CJ mentioning that automatic font outlines *are* generated that way by AGS itself. That was way back in the days of 2.7x though.

David Ostman

Yep.

Which is why if using upscaled pixel fonts we get the upper outline instead of the (probably) desired bottom outline.



Maybe we should be able to control how many pixels the outline font is shifted.

SMF spam blocked by CleanTalk