Old School IV – Yet Another Sine Wave Scroller made in Monkey X

Yet another sine wave scroller. Now the wave moves also — just like in the most traditional Amiga demos. 🙂

Below is the video (new version with smoother movement):

The angle for sin function is calculated from the x-coordinate again. 360 is divided by the screen width = 640 pixels, the quotient is 0.5625. The screen position (in pixels) from 0 to 640 – 1 is multiplied by this quotient which makes the sine wave to be positioned to full screen width.

That’s the idea. In the code the starting position can be negative (minus character’s width).

The variable addAngle is added to the screen position for the sin function, which makes the wave move. If the value of addAngle is negative, the wave moves to the other direction.

Below is the code:

Import mojo2
Import brl.databuffer

Function Main()
	New MyApp
End

Class MyApp Extends App
	
	Const FONT_HEIGHT:Int = 135
	Const SCROLLTEXT:String = "                    Old School IV - Yet another sine wave scroller made in Monkey X... Now also the wave moves...                         "

	Global canvas:Canvas
	Global fontDat:DataBuffer
	Global gfxFont:Image
	Global gfxBG:Image
	Global chrStartOffset:Int
	Global firstChrWidth:Int
	Global chrEndOffset:Int
	Global angleAdd:Int
	Global lightAngle:Float, lightX:Float, lightY:Float
	Global x:Float
	
	Method OnCreate()
		
		canvas = New Canvas
		
		gfxBG = Image.Load("bg.png",.0,.0)
		gfxFont = Image.Load("font.png")
		fontDat = New DataBuffer(95*4*2) ' 95 characters, for each character two 4 byte integers
		fontDat = DataBuffer.Load("monkey://data/font.dat")

		canvas.SetAmbientLight .2,.3,.7
				
		x = 0
		chrStartOffset = 0
		firstChrWidth = charWidth(0)
		chrEndOffset = getTextEndOffset()
		
		angleAdd = 0

		SetUpdateRate(60)
	End
	
	Method OnUpdate()
		
		lightX = Cos(lightAngle) * 150 + 640 / 2
		lightY = Sin(lightAngle) * 150 + 480 / 2
		
		lightAngle = lightAngle + 1


				
		' If the amount of scrolling is at least the width of the first
		' character to be drawn, increase the starting index where the next
		' character will be drawn by one and handle the end of the string
		If x < -firstChrWidth Then

                     x = firstChrWidth + x

			chrStartOffset = chrStartOffset + 1
			
			If chrStartOffset > SCROLLTEXT.Length - 1 Then chrStartOffset = 0
			
			firstChrWidth = charWidth(chrStartOffset)
			chrEndOffset = getTextEndOffset()
			
			If chrEndOffset > SCROLLTEXT.Length - 1 Then chrEndOffset = 0
			
		Endif

		x = x - 2	' scrolling speed
			
	End
	
	Method OnRender()
		canvas.PushMatrix()
		canvas.Scale(DeviceWidth()/640.0,DeviceHeight()/480.0)

		canvas.Clear
		
		canvas.SetLightType 0,1
		canvas.SetLightColor 0,.7,.7,.9
		canvas.SetLightPosition 0,lightX,lightY,-100
		canvas.SetLightRange 0,200
		
		For Local sx:=0 Until DeviceWidth Step 128
			For Local sy:=0 Until DeviceHeight Step 128	
				canvas.DrawImage gfxBG,sx,sy
			Next
		Next

		canvas.SetBlendMode(BlendMode.Additive)
		
		' draw string to position x
		drawString(x)
		
		canvas.Flush()
		canvas.PopMatrix()	

	End
	
	' This function draws text with sine wave from indexes
	' chrStartOffset to chrEndOffset of the scrolltext string
	Function drawString(x:Int)
		Local angle:Int
		Local index:Int
		Local len = SCROLLTEXT.Length()
		Local i:Int = 0, xx:Int
		Local chrs:Int[]
		chrs = SCROLLTEXT.ToChars()
		xx = x
		For i = chrStartOffset To chrEndOffset
			For Local ii = 0 To fontDat.PeekInt((chrs[i]-32)*4*2 + 4) - 1
				
				canvas.DrawRect(xx, Sin(angle) * 64 + (480 - FONT_HEIGHT) / 2, 1, FONT_HEIGHT, gfxFont, fontDat.PeekInt((chrs[i]-32)*4*2)+ii, 0, 1, FONT_HEIGHT)

				angle = (xx + angleAdd) * 0.5625
				xx = xx + 1
			Next
			angleAdd = angleAdd + 1	' This moves the wave
		Next
	
	End

	' get character's width in pixels
	Function charWidth:Int(offset:Int)
		Local chrs:Int[]
		chrs = SCROLLTEXT.ToChars()
		Return fontDat.PeekInt((chrs[offset]-32)*4*2 + 4)
	End
	
	Function getTextEndOffset:Int()
		Local chrs:Int[]
		Local c:Int = chrStartOffset
		Local textWidth:Int = 0
		
		chrs = SCROLLTEXT.ToChars()
		
		' Find the end offset for a character to build a string
		' that's width in pixels is at least 640 + first character's width
		While textWidth < 640 + firstChrWidth
			textWidth = textWidth + charWidth(c)
			c = c + 1

			If c > SCROLLTEXT.Length - 1 Then c = 0
			
		Wend
		
		Return c
		
	End
	
End Class

Check the other Old School posts for more info and feel free to use this code.

%d bloggers like this: