How to get timestamp in Monkey 2 with libc and in C

This morning I got implemented a little code, that can be used to get timestamp based on ANSI C code using Monkey 2 programming language’s libc.

Let’s take first look at the Monkey 2 code:

Namespace myapp

#Import "<std>"
#Import "<libc>"

Using std..
Using libc..

Function Main()

		Local seconds:time_t
		Local p:tm_t Ptr
		Local date:String
		
		libc.time(Varptr seconds)
	
		p = localtime(Varptr seconds)
		
		date = String(p->tm_sec) + "-" + String(p->tm_min) + "-" + String(p->tm_hour) + "-" + String(p->tm_mday) + "-" + String((p->tm_mon)+1) + "-" + String(1900 + p->tm_year)
		
		Print date
	
End

At the moment the output of the program is as follows: 40-31-8-26-10-2018

Year 2018, month 10, day 26, hour 8, min 31, sec 40.

Reversed order might be more useful in practice…

Let’s take a look at the C version:

#include <stdio.h>
#include <time.h>

void Date (char date[10+1]);

void main (void) {

	char datum[10+1];
	
	Date(datum);
	printf("%s",datum);

}


void Date (char date[10+1]) {
	time_t seconds;
	struct tm *p;
	
	time (&seconds);
	p = localtime(&seconds);
	
	sprintf(date, "%02i.%02i.%02i",
		p->tm_mday,
		p->tm_mon + 1,
		p->tm_year+1900);
}

To the year is again added 1900. This gives following output: 26.10.2018

The tm_mon is between 0..11, tm_year between 1900 + 0..n.

That’s it for now, lots of things to do…

 

 

Sine Wave Scroller in Monkey2

Today’s little code, sine scroller in Monkey2. In the previous post you can download the code and data files for plain scroller. In this project same data files are used. Let’s take a look at the video:

The scrolling isn’t very smooth in the video, but try the code:

Namespace myapp

#Import "<std>"
#Import "<mojo>"


#Import "gfx/bg.jpg"
#Import "fonts/DoctorJekyllNF.ttf"

Using std..
Using mojo..


Class MyWindow Extends Window

Const SCROLLTEXT:String = "                              Sine scroller programmed in Monkey2 programming language...  One of the traditional sine scrollers seen in Amiga demos...                   "

Field bg:Image
Field scrollString:String
Field scrollX:Int
Field scrollY:Int
Field chrStartOffset:Int
Field firstChrWidth:Int
Field chrEndOffset:Int
Field font:Font

Field angl:Float

	Method New( title:String="Simple sine scroller",width:Int=640,height:Int=480,flags:WindowFlags=Null )

		Super.New( title,width,height,flags )

		bg = Image.Load("asset::bg.jpg")
		font = Font.Load("asset::DoctorJekyllNF.ttf",80)
		
		
		chrStartOffset = 0
		firstChrWidth = font.TextWidth(SCROLLTEXT.Mid(0,1))
		scrollX = 0
		
	End

	Method OnRender( canvas:Canvas ) Override
	
		App.RequestRender()

		canvas.DrawImage(bg,0,0)
		canvas.Font = font
		canvas.Color = Color.Orange
		
					
		If scrollX < -firstChrWidth Then
			
			chrStartOffset = chrStartOffset + 1

			If chrStartOffset > SCROLLTEXT.Length - 1 Then chrStartOffset = 0
			
			firstChrWidth = font.TextWidth(SCROLLTEXT.Mid(chrStartOffset,1))
			chrEndOffset = getTextEndOffset()
			
			If chrEndOffset > SCROLLTEXT.Length - 1 Then chrEndOffset = 0
			
			scrollX = 0
		Endif
				
		
		
				
		Local s:String
		Local position:Int = 0

		For Local c:Int = 0 To scrollString.Length - 1
			s = scrollString.Mid(c,1)
		
			Local angle:Float = ((640.0 / scrollString.Length) / 360.0 * 2) * (Pi / 180) + 8 * (chrStartOffset + c) * (Pi / 180) + angl
			
			scrollY = 200 + Sin(angle) * 80
			canvas.DrawText(s,scrollX+position,scrollY)
			
			position = position + font.TextWidth(scrollString.Mid(c,1))
		Next
		
		scrollX = scrollX - 2
		angl = angl - (Pi / 180) * 4
	End

	
	Method getTextEndOffset:Int()
		Local c:Int = chrStartOffset
		Local textWidth:Int = 0
		
		scrollString = ""
		
		' 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
			
			scrollString = scrollString + SCROLLTEXT.Mid(c,1)
			c = c + 1
						
			If c > SCROLLTEXT.Length - 1 Then c = 0
			
			textWidth = font.TextWidth(scrollString)
		Wend
		
		Return c
		
	End	
		
End

Function Main()

	New AppInstance
	
	New MyWindow
	
	App.Run()
End

The idea is to build a string (“scrollString”) which characters are drawn one by one to the screen in order to achieve the sine wave effect.

Feel free to use this code.

Simple text scrollers in Monkey X and Monkey2

I coded today simple text scrollers in Monkey X and Monkey2. When the old school bug had bitten me I coded among other things the following:

This night it’s time to just simple text scrollers code.

Let’s take a look at the result of the Monkey X code:

The source code:

Import mojo2
Import brl.databuffer
Import mojo.audio

Function Main()
	New MyApp
End
 
Class MyApp Extends App
	
	Const FONT_HEIGHT:Int = 153
	Const SCROLLTEXT:String = "                      Testing plain text scrolling code... Coded in good old Monkey X Pro...  The picture is from my home, when I was living in Turku, Finland...                       "
 
	field canvas:Canvas
	field fontDat:DataBuffer
	field gfxFont:Image
	field gfxBG:Image
	field chrStartOffset:Int
	field firstChrWidth:Int
	field chrEndOffset:Int
	field x:Float

	
	Method OnCreate()
				
		canvas = New Canvas
		
		gfxBG = Image.Load("bg.jpg",.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")
 				
		x = 0
		chrStartOffset = 0
		firstChrWidth = charWidth(0)
		
		SetUpdateRate(15)
	End
	
	Method OnUpdate()
 
		' Scroll the amount of width of the character in the font
		If x < -firstChrWidth Then
			chrStartOffset = chrStartOffset + 1
			
			If chrStartOffset > SCROLLTEXT.Length - 1 Then chrStartOffset = 0
			
			firstChrWidth = charWidth(chrStartOffset)
			chrEndOffset = getTextEndOffset()
			
			If chrEndOffset > SCROLLTEXT.Length - 1 Then chrEndOffset = 0
			
			x = 0
		Endif
 
		x = x - 2	' scrolling speed
			
	End
	
	Method OnRender()
		canvas.PushMatrix()
'		canvas.Scale(DeviceWidth()/640.0,DeviceHeight()/480.0)
 
 		canvas.SetBlendMode(BlendMode.Alpha)
		canvas.DrawImage(gfxBG,0,0)
 
		canvas.SetBlendMode(BlendMode.Additive)
		
		' draw string to position x
		drawString(x)
		
		canvas.Flush()
		canvas.PopMatrix()	
 
	End
	
	' This function draws text from indexes
	' chrStartOffset to chrEndOffset of the scrolltext string
	Method drawString(x:Int)
		Local xx:float
		Local angle:Int
		Local index:Int
		Local len = SCROLLTEXT.Length()
		Local chrs:Int[]
		chrs = SCROLLTEXT.ToChars()
		Local prevChrWidth:Int
		
		For Local i:Int = chrStartOffset To chrEndOffset
			canvas.DrawRect(x+prevChrWidth, (480 - FONT_HEIGHT) / 2, fontDat.PeekInt((chrs[i]-32)*4*2 + 4), FONT_HEIGHT, gfxFont, fontDat.PeekInt((chrs[i]-32)*4*2), 0, fontDat.PeekInt((chrs[i]-32)*4*2 + 4), FONT_HEIGHT)
			prevChrWidth = prevChrWidth + fontDat.PeekInt((chrs[i]-32)*4*2 + 4)
		Next		

	End
 
	' get character's width in pixels
	Method charWidth:Int(offset:Int)
		Local chrs:Int[]
		chrs = SCROLLTEXT.ToChars()
		Return fontDat.PeekInt((chrs[offset]-32)*4*2 + 4)
	End
	
	Method getTextEndOffset:Int()
		Local chrs:Int[]
		Local c:Int = chrStartOffset
		Local textWidth:Int = 0
		
		chrs = SCROLLTEXT.ToChars()
		
		' Find the endoffset 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

For the font I’ve used my Font 2 PNG and its data file. Notice, that the update rate is only 15, change that to 60.

 

For the first time I made a text scroller in Monkey2 too. The result is in video below:

As you can see, the code is a little different:

Namespace myapp

#Import "<std>"
#Import "<mojo>"

#Import "gfx/bg.jpg"
#Import "fonts/DoctorJekyllNF.ttf"

Using std..
Using mojo..

Class MyWindow Extends Window

Const SCROLLTEXT:String = "                              Testing simple text scrolling code written in Monkey2...  Later it's time again for old school sine scrollers...                     "

Field bg:Image
Field scrollString:String
Field scrollX:Int
Field chrStartOffset:Int
Field firstChrWidth:Int
Field chrEndOffset:Int
Field font:Font
	
	Method New( title:String="Simple mojo app",width:Int=640,height:Int=480,flags:WindowFlags=Null )

		Super.New( title,width,height,flags )

		bg = Image.Load("asset::bg.jpg")
		font = Font.Load("asset::DoctorJekyllNF.ttf",80)
		
		scrollX = 0
		chrStartOffset = 0
		firstChrWidth = font.TextWidth(SCROLLTEXT.Mid(0,1))

	End

	Method OnRender( canvas:Canvas ) Override
	
		App.RequestRender()

		canvas.DrawImage(bg,0,0)
		canvas.Font = font
		canvas.Color = Color.Orange
				
		If scrollX < -firstChrWidth Then
			chrStartOffset = chrStartOffset + 1
			
			If chrStartOffset > SCROLLTEXT.Length - 1 Then chrStartOffset = 0
			
			firstChrWidth = font.TextWidth(SCROLLTEXT.Mid(chrStartOffset,1))
			chrEndOffset = getTextEndOffset()
			
			If chrEndOffset > SCROLLTEXT.Length - 1 Then chrEndOffset = 0
			
			scrollX = 0
		Endif
				
		canvas.DrawText(scrollString,scrollX,200)

		scrollX = scrollX - 2
		
	End

	
	Method getTextEndOffset:Int()
		Local c:Int = chrStartOffset
		Local textWidth:Int = 0
		
		scrollString = ""
		
		' 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
			
			scrollString = scrollString + SCROLLTEXT.Mid(c,1)
			textWidth = textWidth + font.TextWidth(SCROLLTEXT.Mid(c,1))
			c = c + 1
						
			If c > SCROLLTEXT.Length - 1 Then c = 0
			
		Wend
		
		Return c
		
	End	
		
End

Function Main()

	New AppInstance
	
	New MyWindow
	
	App.Run()
End

In order the get coding going, you may download both the projects with all the data files. Password to download: scroller

Later it’s time to again for sine wave scrollers… 🙂

Have fun!

Unique Random Integers part II

Last year I wrote about my clumsy implementation of unique random integers system, I’ve used in my Memorable Ladies games. In those the speed isn’t a critical factor. It’s sufficient that the idea works. 🙂

In this post the idea behind unique random integers is the same, but implemented in a faster way.

In the implementation I have used an array that consists of all desired integers and each is drawn in a way that the same integer doesn’t get drawn again. Let’s take a look at the code (I have used Monkey2 programming language in the example):

Namespace myapp

#Import "<std>"

Using std..

Function Main()

	Local index:Int
	Local amountNumbers:Int
	Local randomNumber:Int
	Local numbers:=New Int[](1,3,5,7,9,11,13,15,17,19,21,23)

	While (numbers.Length <> 0)
		
		amountNumbers = numbers.Length	
		index = Int(amountNumbers * Rnd(0,1)) Mod amountNumbers
		randomNumber = numbers[index]
		
		For Local i:Int = index To amountNumbers - 2
			numbers[i] = numbers[i+1]
		Next
		
		amountNumbers = amountNumbers - 1
		numbers = numbers.Resize(amountNumbers)	
				
		Print "Random number:" + randomNumber

	End While
	
End

Image courtesy of nonicknamephoto at FreeDigitalPhotos.net

First an array is initialized with desired integers. Then an random integer from the array is fetched using random index inside the array.  After that the numbers after the drawn number are moved to “left”. For the end the amount of integers is decreased by 1 and the array is resized by the new amount of integers. That’s it.

This way one gets always different random integer from the set of desired integers.

Furthermore, if one would like to get, for example, number four (4) to be drawn three times, one could just include 4 three times in the array.

Depending on what one is doing, one could keep a copy of the original array for future usage.

Although I have used Monkey2 as example programming language, it should be easy to implement similar implementation to many other programming languages quite straight forwardly.

 

 

Scaling ttf-font in Monkey2

In Monkey2 programming language it is possible to load ttf (and otf & fon) font directly and use the DrawText method of canvas to draw the text. But how to scale the font? In this example I made today it is done in a clumsy way, but may give you some ideas…

The source code:

Namespace myapp

#Import "IMG_0648.JPG"
#Import "transparent.png"

#Import "<std>"
#Import "<mojo>"

Using std..
Using mojo..


Class MyWindow Extends Window
	
	Const RAD:Double = Pi / 180	' 1 degreen in radians
	
	Field gfxBG:Image
	Field gfxTransparent:Image	' Just an transparent image where the text is drawn
	Field fontCanvas:Canvas		' Canvas for transparent image
	Field scaleVar:Float
	Field scale:Float			' Text scale (scales the "gfxTransparent")

	Method New( title:String="Scaling font in Monkey2",width:Int=800,height:Int=600,flags:WindowFlags=Null )
		Super.New( title,width,height,flags )
		
		gfxBG = Image.Load("asset::IMG_0648.JPG")

		' Load a 100 x 48 transparent image
		gfxTransparent = Image.Load("asset::transparent.png")		
		gfxTransparent.Handle = New Vec2f(0, 0)

		' Make a canvas from the transparent image to render the text to...
		fontCanvas = New Canvas(gfxTransparent)
		fontCanvas.Font = Font.Load("asset::SpeedballNo2NF.ttf", 21)
		fontCanvas.Color = Color.Yellow
		fontCanvas.DrawText("Sample Text",(100 - fontCanvas.Font.TextWidth("Sample Text")) / 2, 1)
		fontCanvas.Flush()		

		scale = 1
		scaleVar = 0
	End

	Method OnRender(canvas:Canvas) Override
	
		App.RequestRender()

		canvas.DrawImage(gfxBG, 0, 0)
		
		scaleVar = scaleVar + RAD * 2
		scale = 4 - Sin(scaleVar) * 1.5	' This the scale (if scale = 1, no scaling)
				
		' The text is scaled and centered
		canvas.DrawImage(gfxTransparent, (800 - 100.0 * scale) / 2, (600 - 48.0 * scale) / 2, 0, scale, scale)

		canvas.Flush()
		
	End

End

Function Main()
	New AppInstance
	New MyWindow
	App.Run()
End

Below is the video related to this post:

Feel free to use my code!

Scrolling of Picture Larger Than Visible Area in Monkey2

I finally today made my first Monkey2 app. I think it was someday in September I finally noticed that Monkey X has evolved into hugely more advanced programming language: Monkey2.

As I wrote in previous post I have an unfinished game project in Monkey X Pro. I think think I’ll finish it someday in Monkey2… I have one other little project in my mind to be done in Monkey2.

This is why I decided to try to make my first Monkey2 program today. In my older post I wrote a  short tutorial on scrolling a picture larger than visible area in Monkey X Pro keeping Android target in mind. In this post the same thing is written in Monkey2 to desktop.

The picture is scrolled with mouse, to change the code to touch screen, just change the mouse related code to touch related code.

Source code below:

' Scrolling of pre-loaded picture that is larger than the visible area in Monkey2
'

Namespace myapp

#Import "bg1280x960.png"
#Import "<std>"
#Import "<mojo>"

Using std..
Using mojo..

Class MyWindow Extends Window

	Field gfxBG:Image
	Field scrollX:Float
	Field scrollY:Float
	Field touchX:Float
	Field touchY:Float
	Field touchXD:Float
	Field touchYD:Float
	Field prevTX:Float
	Field prevTY:Float
	Field scroll:Bool
	
	Method New( title:String="Scrolling...",width:Int=800,height:Int=600,flags:WindowFlags=Null )
		Super.New(title,width,height,flags )
		gfxBG = Image.Load("asset::bg1280x960.png")
	End
	
	Method OnRender( canvas:Canvas ) Override
	
		App.RequestRender()

		If scrollX > 0 Then scrollX = 0
		If scrollX < -(1280 - 800) + 1 Then scrollX = -(1280 - 800) + 1
		If scrollY > 0 Then scrollY = 0
		If scrollY < -(960 - 600) + 1 Then scrollY = -(960 - 600) + 1
		
		canvas.DrawImage(gfxBG,scrollX, scrollY)
		
	End
	
	Method OnMouseEvent( event:MouseEvent ) Override
	
		touchX = Mouse.X
		touchY = Mouse.Y
					
		If Mouse.ButtonDown(MouseButton.Left) Then
			
			If scroll = True Then

				' touchXD & touchYD variables prevent the picture
				' to "jump", if scrolling is stopped and user then
				' touches somewhere on the screen				

				touchXD = touchX
				touchYD = touchY
				
			Else
				' if not scrolling, values below are set to zero,
				' because when the scrolling starts again, otherwise
				' scrollX & scrollY could change too much because of
				' values of previous scrolling
								
				touchXD = 0
				touchYD = 0
				prevTX = 0
				prevTY = 0
			
			Endif
			
			scroll = True
				
			scrollX = scrollX - (touchXD - prevTX)
			scrollY = scrollY - (touchYD - prevTY)
			
			prevTX = touchX
			prevTY = touchY

		Else
			scroll = False			
		Endif

	End
		
End

Function Main()

	New AppInstance	
	New MyWindow
	
	App.Run()
End

Video below demos the source (the text in the video is in video only, though):

https://youtu.be/U9DLogNGeoo

Below is a video from the mentioned older blog post written in Monkey X Pro to Android:

Feel free to use my code as you wish.