yet another sinus scroller question

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

Re: yet another sinus scroller question

Post by phipslk »

thank you for your help! SelectBrush() enlightend me ;-) this one works even on an Amiga (with PiStorm, I admit) fine.
I use Cls() because I did a star field moving in background. Is it really better to clear only the "old" pixels even from starfield instead of using Cls()?
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 »

phipslk wrote: Mon Dec 11, 2023 5:59 pm I use Cls() because I did a star field moving in background. Is it really better to clear only the "old" pixels even from starfield instead of using Cls()?
It might depend how full of stars it is, but most likely it's better to avoid Cls() still. You'll see the definite answer when you measure time spend on drawing a frame or certain amount of frames with both methods. Use StartTimer() and print GetTimer() to see how many milliseconds it takes to render frame(s). Try to get time spent per frame as low as possible, even small improvements matter when you push tens of frames per second in the final product.
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

Re: yet another sinus scroller question

Post by phipslk »

I changed the code along your tips, so I don't have to use Cls() anymore. It is faster, that's true. But still too demanding for a real machine. Even in high speed emulation the demo is far to slow....

Code: Select all

; starfield
;@REQUIRE planarama.hwb
@DISPLAY {Width = 640, Height = 500, Mode = "FullScreen"}
@MUSIC 1, "blaizer.mod"
@BRUSH 2,"amigalogo.jpg", {x= 0, y = 0, ScaleWidth = 284, Scaleheight = 120}
@BRUSH 1,"80sfont.png"		; font

CreateFont(1,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ*%: 0123456789!'()?-/.,",32,34,10)
UseFont(1)

Const #SIZE = 32
Const #HEIGHT = 34

t$ = 	" * Hi everybody! *   :  " ..
	"This is a first try of coding a demo with HOLLYWOOD-MAL "..
	" and it looks quite nice, doesn't it?   "
t$ = UpperStr(t$)
tlen = StrLen(t$)
ytable = {}

chars_on_screen = Int(GetAttribute(#DISPLAY, 1, #ATTRWIDTH) / #SIZE) 	; no float numbers for tables ;-)
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, #HEIGHT, #BLACK)
	SelectBrush(char_brush[char$])
		TextOut(0, 0, char$)
	EndSelect
    EndIf
Next

; table with sinus values for scrolltext
ytable={
     50,49,48,47,46,45,44,43,43,42,41,40,39,38,37,37,
     36,35,34,33,32,32,31,30,29,28,28,27,26,25,24,24,
     23,22,21,21,20,19,19,18,17,17,16,15,15,14,13,13,
     12,12,11,11,10,9,9,8,8,7,7,7,6,6,5,5,
     4,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,
     3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,10,
     10,11,11,12,13,13,14,14,15,16,16,17,18,18,19,20,
     20,21,22,23,23,24,25,26,26,27,28,29,30,30,31,32,
     33,34,34,35,36,37,38,39,40,40,41,42,43,44,45,46,
     46,47,48,49,50,51,52,53,53,54,55,56,57,58,59,59,
     60,61,62,63,64,65,65,66,67,68,69,69,70,71,72,73,
     73,74,75,76,76,77,78,79,79,80,81,81,82,83,83,84,
     85,85,86,86,87,88,88,89,89,90,90,91,91,92,92,93,
     93,94,94,94,95,95,95,96,96,96,97,97,97,97,98,98,
     98,98,99,99,99,99,99,99,99,99,99,99,99,99,99,99,
     99,99,99,99,99,99,99,99,99,98,98,98,98,98,97,97,
     97,97,96,96,96,95,95,95,94,94,93,93,92,92,92,91,
     91,90,90,89,88,88,87,87,86,86,85,84,84,83,82,82,
     81,80,80,79,78,78,77,76,75,75,74,73,72,71,71,70,
     69,68,67,67,66,65,64,63,62,62,61,60,59,58,57,56,
     56,55,54,53,52,51,50,50
}


; 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

star_max_y = GetAttribute(#DISPLAY, 1, #ATTRHEIGHT) + GetAttribute(#DISPLAY, 1, #ATTRWIDTH)/2
star_num = 199

; start values for color bars
bar_y=142
bar_one_y = 10
bar_two_y = 145

bar_max = 145
bar_min = 10
bar_one_dir = 2
bar_two_dir = -2
one_fore=False			; which bar is in front

star_dir = 1			; direction of star movement
star_dir_x = 1
star_min=-(GetAttribute(#DISPLAY, 1, #ATTRWIDTH)/2)


; the color bars will cycle through these colors
cols = {$F70000, $F72000, $F74100, $F76100, $F78200, $F7A200, $F7C300, $F7E300, $F7F300, $E7F300,
$C6F300, $A5F300, $84F300, $63F300, $42F300, $21F300, $00F300, $00F321, $00F342, $00F363,
$00F384, $00F3A5, $00F3A5, $00F3C6, $00F3E7, $00F3F7, $00E3F7, $00C3F7, $00A2F7, $0082F7,
$0061F7, $0041F7, $0020F7, $0000F7, $2100F7, $4200F7, $6300F7, $8400F7, $A500F7, $C600F7,
$E700F7, $F700F7, $F700E7, $F700C6}

collength = ListItems(cols)
start2 = collength - 1
scroll_col = 0

; prepare starfield 
Function p_InitStars()

    stars = {}

    For Local i = star_min To star_num ;+ (star_min*-1)

	    stars[i] = {
		x = Rnd(GetAttribute(#DISPLAY, 1, #ATTRWIDTH)+star_min*-1),
		y = Rnd(star_max_y) + star_max_y,
		speed = Rnd(4) + 1,
		color = (Rnd(11) + 4) * 0x111111}

    Next

EndFunction
 
Function bar_one()
	i = start1
;	Box(0,bar_one_y-1,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_one_y+5,#BLACK)	

	For k = 0 To collength - 2
		Line(k * 16, bar_one_y, k * 16 + 15, bar_one_y, cols[i],{Thickness=5})
		i = i + 1
		If i = collength Then i = 0
	Next

	Line(k * 16, bar_one_y, GetAttribute(#DISPLAY, 1, #ATTRWIDTH), bar_one_y, cols[i],{Thickness=5})

	start1 = start1 + 1
	If start1 = collength Then start1 = 0

EndFunction

Function bar_two()
; display lower color bar (reverse direction!)

	i = start2
	
;	Box(0,bar_two_y-1,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_two_y+5,#BLACK)	
	
	For k = collength * 2 To 1 Step -1
		Line(k * 16 + 15, bar_two_y, k * 16,bar_two_y, cols[i],{Thickness=5})
		i = i - 1
		If i = -1 Then i = collength - 1
	Next

	Line(18, bar_two_y, 0, bar_two_y, cols[i],{Thickness=5})

	start2 = start2 - 1
	If start2 = -1 Then start2 = collength - 1
EndFunction

Function sine_scroll()
;    DisableLineHook()
	SetFillStyle(#FILLCOLOR)
	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, #HEIGHT, #BLACK)
	; Calculate new position
	x = x - 4
	y = ytable[Wrap(Int(x/2), 1, 360)]+(GetAttribute(#DISPLAY, 1, #ATTRHEIGHT)-300)
	; 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

Function draw_starfield()
;	Local bar_front = 2
;	DisableLineHook()
;	Cls
	Box(0,bar_one_y-4,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_one_y+5,#BLACK)	
	Box(0,bar_two_y-4,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_two_y+5,#BLACK)	

	sine_scroll()	
	vy = vy + dir
	If vy=range Then dir = -1
	If vy=-range Then dir = 1	

	For i = star_min To star_num
		Plot(stars[i].x,stars[i].y,#BLACK)
		If stars[i].y >= star_max_y Then stars[i].y = stars[i].y - star_max_y
		If stars[i].x <= star_min Then stars[i].x = stars[i].x + GetAttribute(#DISPLAY, 1, #ATTRWIDTH)
		stars[i].x = (stars[i].x - (stars[i].speed) * star_dir_x)
		stars[i].y = stars[i].y + star_dir * star_dir_x
		Plot(stars[i].x, stars[i].y, stars[i].color)		
	Next
	
	If one_fore= True Then bar_two() Else bar_one()
	DisplayBrush(2,#CENTER,20) 	; show picture
	If one_fore= True Then bar_one() Else bar_two()

	bar_one_y = bar_one_y + bar_one_dir
	bar_two_y = bar_two_y + bar_two_dir

	If bar_one_y >= bar_max
		bar_one_dir = -2
		bar_two_dir = 2
		one_fore = True
	EndIf
	If bar_one_y <= bar_min
		bar_one_dir = 2
		bar_two_dir = -2
		one_fore = False
	EndIf
	
	Flip

	Local e = TimerElapsed(1)
	Local f = TimerElapsed(2)
	If e = True Then star_dir = star_dir * -1
	If f = True Then star_dir_x = star_dir_x * -1 
	If x<=-width Then x=GetAttribute(#DISPLAY, 1, #ATTRWIDTH)
;	EnableLineHook()
	
EndFunction

p_InitStars()
;SetFillStyle(#FILLNONE)
EscapeQuit(True)
PlayMusic(1)
SetInterval(1, draw_starfield, 1000/50)		; run function draw_starfiel() @ 50fps
StartTimer(1,3000)
StartTimer(2,5000)
HidePointer()
DisableLineHook()

BeginDoubleBuffer

Repeat
	WaitEvent
Forever
phipslk
Posts: 24
Joined: Sun Oct 29, 2023 7:21 pm

Re: yet another sinus scroller question

Post by phipslk »

a little update for speed winning. Now the starfield is only drawn when visible on screen. gives a little speedup, but still too demanding for an Amiga 1200 with Pistorm...

No use of Cls(), every pixel (at least I hope so ;-) ) only drawn when on screen.

Code: Select all

; starfield
;@REQUIRE planarama.hwb
@DISPLAY {Width = 640, Height = 500, Mode = "FullScreen"}
@MUSIC 1, "blaizer.mod"
@BRUSH 2,"amigalogo.jpg", {x= 0, y = 0, ScaleWidth = 284, Scaleheight = 120}
@BRUSH 1,"80sfont.png"		; font

CreateFont(1,1,"ABCDEFGHIJKLMNOPQRSTUVWXYZ*%: 0123456789!'()?-/.,",32,34,10)
UseFont(1)

Const #SIZE = 32
Const #HEIGHT = 34

t$ = 	" * Hi everybody! *   :  " ..
	"This is a first try of coding a demo with HOLLYWOOD-MAL "..
	" and it looks quite nice, doesn't it?   "
t$ = UpperStr(t$)
tlen = StrLen(t$)
ytable = {}

chars_on_screen = Int(GetAttribute(#DISPLAY, 1, #ATTRWIDTH) / #SIZE) 	; no float numbers for tables ;-)
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, #HEIGHT, #BLACK)
	SelectBrush(char_brush[char$])
		TextOut(0, 0, char$)
	EndSelect
    EndIf
Next

; table with sinus values for scrolltext
ytable={
     50,49,48,47,46,45,44,43,43,42,41,40,39,38,37,37,
     36,35,34,33,32,32,31,30,29,28,28,27,26,25,24,24,
     23,22,21,21,20,19,19,18,17,17,16,15,15,14,13,13,
     12,12,11,11,10,9,9,8,8,7,7,7,6,6,5,5,
     4,4,4,3,3,3,2,2,2,2,1,1,1,1,1,0,
     0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
     0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,
     3,4,4,4,5,5,5,6,6,7,7,8,8,9,9,10,
     10,11,11,12,13,13,14,14,15,16,16,17,18,18,19,20,
     20,21,22,23,23,24,25,26,26,27,28,29,30,30,31,32,
     33,34,34,35,36,37,38,39,40,40,41,42,43,44,45,46,
     46,47,48,49,50,51,52,53,53,54,55,56,57,58,59,59,
     60,61,62,63,64,65,65,66,67,68,69,69,70,71,72,73,
     73,74,75,76,76,77,78,79,79,80,81,81,82,83,83,84,
     85,85,86,86,87,88,88,89,89,90,90,91,91,92,92,93,
     93,94,94,94,95,95,95,96,96,96,97,97,97,97,98,98,
     98,98,99,99,99,99,99,99,99,99,99,99,99,99,99,99,
     99,99,99,99,99,99,99,99,99,98,98,98,98,98,97,97,
     97,97,96,96,96,95,95,95,94,94,93,93,92,92,92,91,
     91,90,90,89,88,88,87,87,86,86,85,84,84,83,82,82,
     81,80,80,79,78,78,77,76,75,75,74,73,72,71,71,70,
     69,68,67,67,66,65,64,63,62,62,61,60,59,58,57,56,
     56,55,54,53,52,51,50,50
}


; 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

star_max_y = GetAttribute(#DISPLAY, 1, #ATTRHEIGHT) + GetAttribute(#DISPLAY, 1, #ATTRWIDTH)/2
star_num = 199

; start values for color bars
bar_y=142
bar_one_y = 10
bar_two_y = 145

bar_max = 145
bar_min = 10
bar_one_dir = 2
bar_two_dir = -2
one_fore=False			; which bar is in front

star_dir = 1			; direction of star movement
star_dir_x = 1
star_min=(GetAttribute(#DISPLAY, 1, #ATTRWIDTH)/2)*-1


; the color bars will cycle through these colors
cols = {$F70000, $F72000, $F74100, $F76100, $F78200, $F7A200, $F7C300, $F7E300, $F7F300, $E7F300,
$C6F300, $A5F300, $84F300, $63F300, $42F300, $21F300, $00F300, $00F321, $00F342, $00F363,
$00F384, $00F3A5, $00F3A5, $00F3C6, $00F3E7, $00F3F7, $00E3F7, $00C3F7, $00A2F7, $0082F7,
$0061F7, $0041F7, $0020F7, $0000F7, $2100F7, $4200F7, $6300F7, $8400F7, $A500F7, $C600F7,
$E700F7, $F700F7, $F700E7, $F700C6}

collength = ListItems(cols)
start2 = collength - 1
scroll_col = 0

; prepare starfield 
Function p_InitStars()

    stars = {}

    For Local i = star_min To star_num ;+ (star_min*-1)

	    stars[i] = {
		x = Rnd(GetAttribute(#DISPLAY, 1, #ATTRWIDTH)+star_min*-1),
		y = Rnd(star_max_y) + star_max_y,
		speed = Rnd(4) + 1,
		color = (Rnd(11) + 4) * 0x111111}

    Next

EndFunction
 
Function bar_one()
	i = start1
;	Box(0,bar_one_y-1,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_one_y+5,#BLACK)	

	For k = 0 To collength - 2
		Line(k * 16, bar_one_y, k * 16 + 15, bar_one_y, cols[i],{Thickness=5})
		i = i + 1
		If i = collength Then i = 0
	Next

	Line(k * 16, bar_one_y, GetAttribute(#DISPLAY, 1, #ATTRWIDTH), bar_one_y, cols[i],{Thickness=5})

	start1 = start1 + 1
	If start1 = collength Then start1 = 0

EndFunction

Function bar_two()
; display lower color bar (reverse direction!)

	i = start2
	
;	Box(0,bar_two_y-1,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_two_y+5,#BLACK)	
	
	For k = collength * 2 To 1 Step -1
		Line(k * 16 + 15, bar_two_y, k * 16,bar_two_y, cols[i],{Thickness=5})
		i = i - 1
		If i = -1 Then i = collength - 1
	Next

	Line(18, bar_two_y, 0, bar_two_y, cols[i],{Thickness=5})

	start2 = start2 - 1
	If start2 = -1 Then start2 = collength - 1
EndFunction

Function sine_scroll()
;    DisableLineHook()
	SetFillStyle(#FILLCOLOR)
	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, #HEIGHT, #BLACK)
	; Calculate new position
	x = x - 4
	y = ytable[Wrap(Int(x/2), 1, 360)]+(GetAttribute(#DISPLAY, 1, #ATTRHEIGHT)-300)
	; 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

Function draw_starfield()
;	Local bar_front = 2
;	DisableLineHook()
;	Cls
	Box(0,bar_one_y-4,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_one_y+5,#BLACK)	
	Box(0,bar_two_y-4,GetAttribute(#DISPLAY, 1, #ATTRWIDTH),bar_two_y+5,#BLACK)	

	vy = vy + dir
	If vy=range Then dir = -1
	If vy=-range Then dir = 1	

	For i = star_min To star_num
		Plot(stars[i].x,stars[i].y,#BLACK)
		If stars[i].y >= star_max_y Then stars[i].y = stars[i].y - star_max_y
		If stars[i].x <= star_min Then stars[i].x = stars[i].x + GetAttribute(#DISPLAY, 1, #ATTRWIDTH)
		stars[i].x = (stars[i].x - (stars[i].speed) * star_dir_x)
		stars[i].y = stars[i].y + star_dir * star_dir_x
		If stars[i].x>=0 And stars[i].x<=GetAttribute(#DISPLAY, 1, #ATTRWIDTH) And stars[i].y>=0 And stars[i].y<=GetAttribute(#DISPLAY, 1, #ATTRHEIGHT)
			Plot(stars[i].x, stars[i].y, stars[i].color)		
		EndIf
	Next

	sine_scroll()	
	
	If one_fore= True Then bar_two() Else bar_one()
	DisplayBrush(2,#CENTER,20) 	; show picture
	If one_fore= True Then bar_one() Else bar_two()

	bar_one_y = bar_one_y + bar_one_dir
	bar_two_y = bar_two_y + bar_two_dir

	If bar_one_y >= bar_max
		bar_one_dir = -2
		bar_two_dir = 2
		one_fore = True
	EndIf
	If bar_one_y <= bar_min
		bar_one_dir = 2
		bar_two_dir = -2
		one_fore = False
	EndIf
	
	Flip

	Local e = TimerElapsed(1)
	Local f = TimerElapsed(2)
	If e = True Then star_dir = star_dir * -1
	If f = True Then star_dir_x = star_dir_x * -1 
	If x<=-width Then x=GetAttribute(#DISPLAY, 1, #ATTRWIDTH)
;	EnableLineHook()
	
EndFunction

p_InitStars()
;SetFillStyle(#FILLNONE)
EscapeQuit(True)
PlayMusic(1)
SetInterval(1, draw_starfield, 1000/50)		; run function draw_starfiel() @ 50fps
StartTimer(1,3000)
StartTimer(2,5000)
HidePointer()
DisableLineHook()

BeginDoubleBuffer

Repeat
	WaitEvent
Forever
Post Reply