One time text fade it and out

Find quick help here to get you started with Hollywood
Post Reply
User avatar
Clyde
Posts: 104
Joined: Sun Feb 14, 2010 1:38 pm
Location: Dresden / Germany

One time text fade it and out

Post by Clyde » Tue Nov 06, 2018 1:05 am

Hey there!

Slowly beginning to do some basic stuff with Hollywood again ...

I would like to fade in a text, have it shown for x seconds and fade it out afterwards. I thought I could use "DisplayTextObjectFX()" but with the #FADE operation it fades the text in and out in a loop which I cannot control:

Code: Select all

SetFontColor(#RED)
SetFont("times.font", 18)
readyMessageID = CreateTextObject(Nil, "Ready")

Function p_MainLoop()

	DisplayTextObjectFX(readyMessageID, #CENTER, #CENTER, {Type = #FADE, Speed = 5, Parameter = #BLACK})  
	
EndFunction

SetInterval(1, p_MainLoop, 40)

While quit = False 
	WaitEvent 
Wend
Basically I have this problems with this code:
1. Speed is a bit unclear. I can't control exact seconds/milliseconds/ticks
2. I cannot set a time where the text stays displayed. And as there is no event when the fade in anim is completed I cannot simply delete this TextObject and replace it by a new one with no FX
3. How to stop the fade in/fade out process after one iteration. It does not help to call it outside the main loop

Any ideas/best practices?

Thanks in advance!
Currently using: Hollywood 7.1 with Windows IDE

PEB
Posts: 184
Joined: Sun Feb 21, 2010 2:28 am

Re: One time text fade it and out

Post by PEB » Tue Nov 06, 2018 4:57 am

The problem with your code is that you keep calling the same function over and over again with a fast interval.

This is one way you can adjust it to get what you want:

Code: Select all

EnableLayers()

SetFontColor(#RED)
SetFont("times.font", 18)

readyMessageID = CreateTextObject(Nil, "Ready")

Function p_DisplayReadyText()
	DisplayTextObjectFX(readyMessageID, #CENTER, #CENTER, {Type = #FADE, Speed = 5, Parameter = #BLACK})
	SetLayerName(0, "ReadyText")
	Wait(50)
	RemoveLayerFX("ReadyText", {Type = #FADE, Speed = 5, Parameter = #BLACK})
EndFunction

p_DisplayReadyText

Repeat
	WaitEvent
Forever

User avatar
Clyde
Posts: 104
Joined: Sun Feb 14, 2010 1:38 pm
Location: Dresden / Germany

Re: One time text fade it and out

Post by Clyde » Tue Nov 06, 2018 11:22 am

Thanks a lot, PEB!

Yeah, I was also worrying about the code is called in my main loop. But I am quite sure I also put DisplayTextObjectFX() out of the main loop so it was only called once. But I will double check it.

One problem is the the Wait() command you use. If I understand it correctly it blocks the whole script so while waiting the given amount of time the script would not react to events like keypresses, would it?

I think I also got some fundamental problems with understanding the game loop or better: what to put in the game loop. In the end I want to do a very simple game regarding game mechanics. Now, I know I have to put the graphics display code and retrieving inputs into this game loop (which runs at 25 fps e.g.). So I thought I also have to put these text display stuff in this game loop, either directly (like or did) or through some kind of event which is evaluated in the loop and depending on game state some other function is called. But this seems to be wrong at least for this display fx stuff?

Confusing, but I know it is not Hollywood's fault but my mental capabilities. :-( :-)
Currently using: Hollywood 7.1 with Windows IDE

User avatar
Clyde
Posts: 104
Joined: Sun Feb 14, 2010 1:38 pm
Location: Dresden / Germany

Re: One time text fade it and out

Post by Clyde » Tue Nov 06, 2018 11:32 pm

Ok, that helped a lot, PEB.

Obviously I was wrong when I said that the behaviour is the same wether I call DisplayTextObjectFX() inside the main loop or outside. It really works the way I want it when I do it your way.

I've overcome the blocking of Wait() in using a timeout, so now I use this:

Code: Select all

Function p_DisplayReadyText()
	DisplayTextObjectFX(readyMessageID, #CENTER, #CENTER, {Type = #FADE, Speed = 5, Parameter = #BLACK})
	
	SetLayerName(0, "ReadyText")
	
	SetTimeout(1, p_FadeoutReadyText, 5000)
EndFunction

Function p_FadeoutReadyText()
	RemoveLayerFX("ReadyText", {Type = #FADE, Speed = 5, Parameter = #BLACK})
EndFunction
Now, I big drawback (for me/this current situation) is, that DisplayTextObjectFX() and RemoveLayerFX() are also blocking the script. This means, a keypress event that I want to detect while this functions run (text is faded in and out) is not recognized/handled. It is just handled after this called are completed.

So, is there a way to implement such kind of effect without blocking the script/event handling is possible while they run?
Currently using: Hollywood 7.1 with Windows IDE

User avatar
Clyde
Posts: 104
Joined: Sun Feb 14, 2010 1:38 pm
Location: Dresden / Germany

Re: One time text fade it and out

Post by Clyde » Wed Nov 07, 2018 12:48 am

It seems I have to work with "Async = True" and "AsyncDrawFrame()"!? I created some really ugly code which should do the trick somehow, but I have to reconsider that code as it seems much too complicated for what I want to achive (that is: listening to keypress event while text is faded it/out).

Maybe someone has a slick idea. Will try to tidy up my code tomorrow anyway so I can show my solution (more kind of a hack, though :-/ )
Currently using: Hollywood 7.1 with Windows IDE

User avatar
Clyde
Posts: 104
Joined: Sun Feb 14, 2010 1:38 pm
Location: Dresden / Germany

Re: One time text fade it and out

Post by Clyde » Wed Nov 07, 2018 11:56 am

Ok, I tidied up my code, but it still a lot. :-/ I hope you understand what I try to achieve anyway and maybe someone has a better approach.

When you run the example hit space when the text fades in.

You can also download the example here: https://1drv.ms/u/s!AvRgnk1wjp43kuwtrtAxHBTjfwElqg

Code: Select all

SetFontColor(#RED) ;

readyMessageID = CreateTextObject(Nil, "Ready")
doneMessageID = CreateTextObject(Nil, "Done")

fps = 30
timeoutID = Nil
textObject = Nil

EnableLayers()

Function p_DummyForTextFading()
	; (unfortunately) needed for setInterval. Otherwise the frame printing loop would not continue
EndFunction

Function p_FadeTextInAsync()
	
	InstallEventHandler({OnKeyUp = p_EventFunc})
	
	SetInterval(2, p_DummyForTextFading, 1000/fps) ; needed, so WaitEvent after AsyncDrawFrame() call continues
	
	textObject = DisplayTextObjectFX(readyMessageID, #CENTER, #CENTER, {Type = #FADE, Speed = 10, Parameter = #BLACK, Async = True})
	
	frames = GetAttribute(#ASYNCDRAW, textObject , #ATTRNUMFRAMES) ; get number of frames to show
	
	For Local k = 1 To frames	
   	    If (IsNil(textObject )) Then Break ; if textObject is Nil, we want to stop playing the fade in
	    
		AsyncDrawFrame(textObject , k) ; draw frame by frame
		
		; VWait or the like are not suitable to use in this case as it blocks the script so no (keypress) event can be handled while anim
		WaitEvent ; needed, so the loop continues (through SetInterval) and listens to keypress events (InstallEventHandler)
   		
	Next
	
	If (IsNil(textObject ) = False) 
		FinishAsyncDraw(textObject ) ; FinishAsyncDraw has to be called
		textObject = Nil
	EndIf

	SetLayerName(0, "ReadyText")
	
	timeoutID = SetTimeout(Nil, p_FadeTextOut, 5000) ; begin to fade out the text after 5 seconds; TODO: make async
	
EndFunction

Function p_FadeTextOut()
	
	RemoveLayerFX("ReadyText", {Type = #FADE, Speed = 5, Parameter = #BLACK}) ; fade out text
	
	; clear variables (important for checks in p_ShowOtherText()
	timeoutID = Nil
	textObject = Nil
	
EndFunction

Function p_ShowOtherText()

	If (IsNil(timeoutID) = False) ; clear Timeout if it is still active
		ClearTimeout(timeoutID)
		timeoutID = Nil
	EndIf
	
	If (IsNil(textObject) = False) ; if the text object is still valid ...
		CancelAsyncDraw(textObject) ; ... cancel the fade in process
		textObject = Nil
	Else
		 If (LayerExists("ReadyText")) Then RemoveLayer("ReadyText")
	EndIf
 	
	DisplayTextObject(doneMessageID, #CENTER, #CENTER) ; show the other text
	
EndFunction

Function p_EventFunc(msg) ; Event Handler
	
	Switch msg.action
		Case "OnKeyUp":
			Switch UpperStr(msg.key)
				Case " ": ; when Space bar was hit ...
				
					p_ShowOtherText() ; ... abort fadein anim of previous text and show other text
					
				Case "ESC":
					End
			EndSwitch
	EndSwitch
	
EndFunction


p_FadeTextInAsync() ; app entry


While quit = False 
	WaitEvent 
Wend

Currently using: Hollywood 7.1 with Windows IDE

PEB
Posts: 184
Joined: Sun Feb 21, 2010 2:28 am

Re: One time text fade it and out

Post by PEB » Thu Nov 08, 2018 9:40 pm

Here's another way you can do it:

Code: Select all

SetFontColor(#RED) ;

readyMessageID = CreateTextObject(Nil, "Ready")
setMessageID = CreateTextObject(Nil, "Set")
goMessageID = CreateTextObject(Nil, "Go")

FadeOrder$={readyMessageID, "remove", setMessageID, "remove", goMessageID, "remove"}
MessageVar=0

fps = 30
timeoutID = Nil
textObject = Nil

EnableLayers()

Function p_PrepFade(WhichText, Case$)
	If Case$="show"
		textObject = DisplayTextObjectFX(WhichText, #CENTER, #CENTER, {Type = #FADE, Speed = 10, Parameter = #BLACK, Async = True})
	ElseIf Case$="remove"
		textObject = RemoveLayerFX("FadingText", {Type = #FADE, Speed = 10, Parameter = #BLACK, Async = True})
	EndIf
	frames = GetAttribute(#ASYNCDRAW, textObject , #ATTRNUMFRAMES) ; get number of frames to show
	FrameCounter=0
	SetInterval(1, p_DoFade, 1000/fps, Case$)
EndFunction

Function p_DoFade(msg)
	FrameCounter=FrameCounter+1
	AsyncDrawFrame(textObject , FrameCounter) ; draw frame by frame
	If FrameCounter=frames
		FinishAsyncDraw(textObject)
		ClearInterval(1)
		If msg.userdata="show"
			SetLayerName(0, "FadingText")
			SetTimeOut(1, p_NextFade, 2000); This sets how long to wait after Text fades IN
		Else
			SetTimeOut(1, p_NextFade, 10); This sets how long to wait after Text fades OUT
		EndIf
	EndIf
EndFunction

Function p_NextFade()
	MessageVar=MessageVar+1
	If MessageVar>ListItems(FadeOrder$)-1; The list of messages has been completed.
		MessageVar=0
	EndIf
	If GetType(FadeOrder$[MessageVar])=#LIGHTUSERDATA
		p_PrepFade(FadeOrder$[MessageVar], "show")
	Else
		p_PrepFade("none", "remove")
	EndIf
EndFunction

ActiveTypingText$="Type During Fade:\n"
TextOut(0, 0, ActiveTypingText$, {Name="ActiveTyping", WordWrap=500})

Function p_ShowTyping(msg)
	ActiveTypingText$=ActiveTypingText$..msg.key
	SetLayerStyle("ActiveTyping", {Text=ActiveTypingText$})
EndFunction

InstallEventHandler({OnKeyDown = p_ShowTyping})

p_PrepFade(readyMessageID, "show")

Repeat
	WaitEvent
Forever
(I don't use #TEXTOBJECT layers in my projects anymore; I prefer to use #TEXTOUT layers instead.)

User avatar
Clyde
Posts: 104
Joined: Sun Feb 14, 2010 1:38 pm
Location: Dresden / Germany

Re: One time text fade it and out

Post by Clyde » Thu Nov 08, 2018 10:57 pm

Wow, this looks very good, PEB. I hope this wasn't too much work for you. :-/ Thanks a lot!
Currently using: Hollywood 7.1 with Windows IDE

PEB
Posts: 184
Joined: Sun Feb 21, 2010 2:28 am

Re: One time text fade it and out

Post by PEB » Sat Nov 10, 2018 5:13 am

Happy to help!

Post Reply