yet another sinus scroller question

Discuss any general programming issues here
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

yet another sinus scroller question

Post by phipslk »

Hi,
I am new to Hollywood and tried to make a sinus scroller. my code seems to work but it's hell to fast... How to slow down? Wait(x) doesn't help, it keeps flickering.

Code: Select all

; sinus scroller

@DISPLAY 1, {width = 360, height = 284}

t$ = 	" * Hi everybody! *                   " ..
	"This is a first try of coding a demo with HOLLYWOOD-MAL "..
	" and it looks quite nice, doesn't it?   "

tlen = StrLen(t$)
charx=360
x = 360
;y = 200
y = {}

For i = 1 To tlen
	CreateTextObject(i,MidStr(t$,i,1))
Next
For i = 1 To 360
	y[i]= Sin(i*50) * 20 + 200
Next

Function sine_scroll()
	Cls()
	For i = 1 To tlen
		DisplayTextObject(i,x+(i*8),y[charx])
;		y[tlen+1]=y[i]
;		RemoveItem(y,0)
;		y = Sin(i) * 100 + 200		
		charx = charx - 1
		If charx <= 1 Then charx = 360
	Next

	x = x - 1
	If x <= -tlen*8 Then x= 360
	Flip
EndFunction

EscapeQuit(True)
BeginDoubleBuffer()

SetInterval(1,sine_scroll,1000/25)
Repeat
	WaitEvent
Forever

plouf
Posts: 473
Joined: Sun Feb 04, 2018 11:51 pm
Location: Athens,Greece

Re: yet another sinus scroller question

Post by plouf »

isnt obvius ?
SetInterval(1,sine_scroll,1000/25) -> SetInterval(1,sine_scroll,1000/12)

However take a look also in cracktros demos from downloads, has some better programming techniques

also checkout CreateFont() new in v10 , its very usefull for these type of cractros
Christos
Bugala
Posts: 1181
Joined: Sun Feb 14, 2010 7:11 pm

Re: yet another sinus scroller question

Post by Bugala »

Commands have arguments. Arguments are the things you put inside ().
SetInterval has following arguments:
ID, Function, TIME

ID is the ID for interval. Idea is that you give ID number for your interval, so that you can at later point use StopInterval(ID) to stop that interval from executing anymore.

Function is the function you wish to run with that interval.

And TIME is how often will that Interval be executed.


Lets say I have simply
Print "Hello World"

And I set it as interval to be executed every 10 seconds. This means that "Hello World" text would be printed every 10 seconds.

If I set that same interval to be executed every 1/4th of a second, then "Hello World" will be printed every 1/4 th of a second.

Therefore, as Plouf pointed out:
SetInterval(1,sine_scroll,1000/25) -> SetInterval(1,sine_scroll,1000/12)

is the solution to your problem, since by adjusting the last argument, that I named as TIME, which in your case is the "1000/25" you can set how often this interval, which means these lines in your function sine_scroll are being executed.

If you set it to 1000/25 these lines will be executed every 1000/25, if you set it to 1000/12, these lines will be executed every 1000/12, which in comparison would make it run about half a speed.

However, do notice that Hollywood will only attempt to execute these lines as often as you set them to be executed with setinterval, but if your machine is too slow to execute these lines as often as you set, then Hollywood will just be executing them as fast as it can.
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

Re: yet another sinus scroller question

Post by phipslk »

thanks for your explanations! but when I reduce the TIME value for SetInterval() then the scroller is still flickering. How can I achieve it to scroll smoother? I looked through the Cracktros but they all use sprites/brushes as it seems and not Text. And I am still working on understanding the code of many cracktros :-)
User avatar
jPV
Posts: 604
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: yet another sinus scroller question

Post by jPV »

Check your Y calculations, I think your Y values jump wildly and makes it look flickering when it technically doesn't flicker (try with a steady Y value).
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

Re: yet another sinus scroller question

Post by phipslk »

jPV wrote: Thu Nov 30, 2023 6:15 pm Check your Y calculations, I think your Y values jump wildly and makes it look flickering when it technically doesn't flicker (try with a steady Y value).
I just had the same idea when I took time down to 1000/6. Okay, probably my sinus routine is not very good. As are my math talents :-)
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

Re: yet another sinus scroller question

Post by phipslk »

okay, so here is a working code. in fact, it's not a sinus scroller but a cosinus scroller. if anyone can give me some hints how to manipulate the sinus/cosinus wave of the scroller, I'd be thankful!
Is there a maximum length of the scrolltext as the routine just moves it out of the screen just counting down. I wondered if there is a limit how far the counter could go out of the screen.

And: it runs fine on windows, but on a real amiga it is terribly slow. What do I have to change to make it run on Amiga too?

Code: Select all

; sinus scroller

@DISPLAY 1, {width = 360, height = 284}

t$ = 	" * Hi everybody! *                   " ..
	"This is a first try of coding a demo with HOLLYWOOD-MAL "..
	" and it looks quite nice, doesn't it?   "

tlen = StrLen(t$)
charx=360
x = 360
y = {}

For i = 1 To tlen
	CreateTextObject(i,MidStr(t$,i,1))
Next

For i = 1 To 360
	y[i]=  10 * Cos(i/3) + 150
Next

Function sine_scroll()
	Cls()
	For i = 1 To tlen
		TextOut(x+(i*16)+1,y[charx]+1,MidStr(t$,i,1),{color = #AQUA,ScaleX = 2.0, ScaleY = 2.0})
		TextOut(x+(i*16),y[charx],MidStr(t$,i,1),{color = #BLUE,ScaleX = 2.0, ScaleY = 2.0})	
		charx = charx - 1
		If charx <= 1 Then charx = 360
	Next

	x = x - 4
	If x <= -tlen*16 Then x= 360
	Flip
EndFunction

EscapeQuit(True)
BeginDoubleBuffer()

SetInterval(1,sine_scroll,1000/25)
Repeat
	WaitEvent
Forever
User avatar
jPV
Posts: 604
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: yet another sinus scroller question

Post by jPV »

Just some quick notes without testing etc.

You'll have to remember that a real Amiga (I assume you mean an Amiga with 68k CPU and slow graphics throughput) is from a whole different world compared to a modern PC, and such an Amiga has a hard time outputting fullscreen chunky graphics at good framerates. Your display is even bigger than a standard lores Amiga display.

You'll have to minimize all graphics drawing operatios and math calculations needed to do on each frame.

Real-time sin/cos calculations are a no-go, which you have already taken into account by creating a cos table, good. Also multiplies and divisions should be avoided as far as possible.

But then you are outputting scalable vector fonts on each frame with TextOut(), which includes very heavy calculations for a 68k CPU. It would be better to pre-render each character as a brush first, because displaying a character would only need copying the brush pixel data into the display without complex math then. I'm not sure if TextObjects would do the same by pre-rendering texts... maybe.. and you are actually creating TextObjects there, but you don't use them anywhere yet. You should use DisplayTextObject() to show them instead of TextOut(). And you create a TextObject for each character in your scroll-text, which would be wasteful with longer scrollers. Maybe it would be better to create a TextObject for each alphabet and then use those accordingly.

Also don't render the whole text for each frame, just render those characters that are on display currently.

And finally, don't clear the whole display with Cls(), just clear the areas that have changed, because why would you want to write data over and over again when it's not changed? The easiest would be to clear the whole scroller area, which would probably reduce the clearing data to 1/10th in your case, but even more efficient would be just to clear the previous text outputs (character dimensions). Or just use sprites for characters and Hollywood does the optimal clearing for you automatically then.

Then, if opting for original Amiga chipsets instead of RTG graphics, I don't know if new palette modes for displays would be better... but I haven't made any tests with them yet...
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

Re: yet another sinus scroller question

Post by phipslk »

thanks for this good explanations. I think, just rendering the letters that are on the screen is most effective, better than rendering the whole scrolltext at once and move it across the screen. that leads me to the next problem :-) how to realize that? I'd not like to use sprites as that don't work with double buffering. I need to create a counter and a check, which letters are shown ... OMG.
User avatar
jPV
Posts: 604
Joined: Sat Mar 26, 2016 10:44 am
Location: RNO
Contact:

Re: yet another sinus scroller question

Post by jPV »

Well.. this isn't anywhere near perfect, but more like a quick proof of concept how to optimize it somehow. Here we have characters as brushes and only render visible ones, and won't clear the whole screen, but just the previous characters. Sin/cos doesn't look like the same etc. but it's just a quick hack and I don't have time or patience to make it better now :)

In any case, your original code made 54% CPU load on my Mac mini G4, but my version makes only under 2% load, so maybe there would be a chance that it'd play on real Amiga too?

Code: Select all

; sinus scroller

@DISPLAY 1, {width = 320, height = 200}

Const #SIZE = 16

t$ = 	" * Hi everybody! *                   " ..
	"This is a first try of coding a demo with HOLLYWOOD-MAL "..
	" and it looks quite nice, doesn't it?   "

tlen = StrLen(t$)
ytable = {}

chars_on_screen = GetAttribute(#DISPLAY, 1, #ATTRWIDTH) / #SIZE
char = {}
text_pos = 0
char_brush = {}

; Render all separate characters in the text as brushes
For Local i = 0 To tlen - 1
    Local char$ = MidStr(t$, i, 1)
    If Not RawGet(char_brush, char$)
        ; Just render a brush if it wasn't done earlier
        char_brush[char$] = CreateBrush(Nil, #SIZE, #SIZE, #BLACK)
        SelectBrush(char_brush[char$])
        TextOut(1, 1, char$, {color = #AQUA, ScaleX = 2.0, ScaleY = 2.0})
        TextOut(0, 0, char$, {color = #BLUE, ScaleX = 2.0, ScaleY = 2.0})
        EndSelect
    EndIf
Next

For Local i = 1 To 360
	ytable[i]=  10 * Cos(i/3) + 150
Next

; Create a table item per visible character.
; Store a corresponding brush and location.
For Local i = 0 To chars_on_screen
    char[i] = {
        brush = char_brush[MidStr(t$, i, 1)],
        x = GetAttribute(#DISPLAY, 1, #ATTRWIDTH) + i * #SIZE,
        y = 0
    }
Next

text_pos = chars_on_screen + 1

Function sine_scroll()
    DisableLineHook()
	For i = 0 To chars_on_screen
        Local x = char[i].x
        Local y = char[i].y
        ; Clear the previous character graphics
        Box(x, y, #SIZE, #SIZE, #BLACK)
        ; Calculate new position
        x = x - 1
        y = ytable[Wrap(x, 1, 360)]
        ; Display a character in new position
        DisplayBrush(char[i].brush, x, y)
        ; If a character is out of the screen, position it back to right
        ; and assign the next character (brush) on it
        If x < - #SIZE
            x = GetAttribute(#DISPLAY, 1, #ATTRWIDTH)
            char[i].brush = char_brush[MidStr(t$, text_pos, 1)]
            text_pos = text_pos + 1
            ; If we're out of text, start over from the beginning
            If text_pos = tlen Then text_pos = 0
        EndIf
        char[i].x = x
        char[i].y = y
	Next
	Flip
    EnableLineHook()
EndFunction

EscapeQuit(True)
BeginDoubleBuffer()

SetFillStyle(#FILLCOLOR)

SetInterval(1,sine_scroll,1000/25)
Repeat
	WaitEvent
Forever
Post Reply