Old School V – A Weird Sine Wave Scroller Made in Monkey X

This is getting to be a nightmare, this is the 5th Old School demonstration made in Monkey X. Probably the last in the series. I must have be bitten by a nostalgia bug.

In this version the lightning effect affects the font too — see the better quality video with new music:

Below is the source code:

Import mojo2
Import brl.databuffer

Function Main()
	New MyApp
End

Class MyApp Extends App
	
	Const FONT_HEIGHT:Int = 219
	Const SCROLLTEXT:String = "          Old School V - A weird sine wave scroller... Now the lightning effect affects the font too...                 "

	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 coefficient:Float
	Global lightAngle:Float, lightX: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
	
		lightX = Cos(lightAngle) * 150 + 640 / 2
		
		SetUpdateRate(60)
	End
	
	Method OnUpdate()
		
		lightX = Cos(lightAngle) * 150 + 640 / 2
		
		lightAngle = lightAngle + 2


				
		' 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, (480 - 128) / 2,-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 coefficient:Float
		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) * 50 + (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 * coefficient
				xx = xx + 1
				coefficient = Sin(xx)				
				
			Next
			angleAdd = 1
		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

The strange variable coefficient causes the weird sine wave effect.

In order to get the lightning effect working for the font, one must create in addition to font.png file files font_n.png and font_s.png. The Mojo2 renderer does the job from that on.

File font.png is light blue as color, font_n.png is graphically the same but white. Font_s.png is darkened version of font_n.png.

As mentioned in the first Old School post, n stands for normal, s stands for specular.

I hope you get the same nostalgic feeling from the video as I get… As always, feel free to use the source.

%d bloggers like this: