Mid, Left & Right functions for Strings in Cerberus X

It’s beginning to be late night, but I want share these with you.

Many of you probably remember Mid, Left and Right functions for strings in basic programming languages.

  • Mid returns from given position x amount of chars
  • Left returns from left x amount of chars
  • Right returns from right x amount of chars

These are easy to implement in Cerberus X, since it has nice string slicing methods.

Implementation for Mid:

Method Mid:String(str:String, startPos:Int, howMany:Int)
        Return str[(startPos)..(startPos+howMany)] 
End

Implementation for Left:

Method Left:String(str:String, howMany:Int)
     Return str[0..howMany]
End

Implementation for Right:

Method Right:String(str:String, howMany:Int) 
     Return str[(str.Length()-howMany)..(str.Length())]
End

You can test these for example with print Mid(“This is String”,5,2).

That’s it for tonight..

Font Class for my Font 2 PNG’s fonts in Cerberus X

My studies keep me really busy and tired… Still, I’m working on Cerberus X version of Easy Math Challenge, because there seems to be problem with sound in Monkey2 with 64-bit compilations for Android.

Anyway, here’s direct implementation (earlier I did this for Monkey X) of font class to use with fonts made in my Font 2 PNG for Cerberus X.

The source (the code is directly from my Cerberus X editor, but highlighting isn’t quite right):

Import mojo2
Import brl.databuffer

Class MyFont
	Field maxHeight:Int
	Field fontDat:DataBuffer
	Field gfxFont:Image
End

Class FontTest Extends App

	Field bg:Image
	Field font1:MyFont
	Field canvas:Canvas
	
	Method OnCreate:Int()

		bg = Image.Load("cerberus://data/bg.jpg",0,0)
		
		' -------
		' Font
		' -------
		font1 = New MyFont
		font1.gfxFont = Image.Load("font.png")
		font1.fontDat = New DataBuffer(95*4*2) ' 95 characters, for each character two 4 byte integers
		font1.maxHeight = 51
		font1.fontDat = DataBuffer.Load("cerberus://data/font.dat")		
		
		canvas = New Canvas()
		
		Return 0
	End

	Method OnRender:Int()
	
		canvas.DrawImage(bg,0,0)

		' drawString assumes, that we have a canvas called canvas
		drawString(font1,"Sample Text", (640 - (stringWidth(font1, "Sample Text"))) / 2, 60)		
		canvas.Flush()
		
		Return 0
	End
	
	Method drawString(font:MyFont, text:String, x:Float, y:Float)
		Local len = text.Length()
		
		Local chrs:Int[]
		chrs = text.ToChars()
		
		For Local i = 0 To len - 1
			'                          width of a character in font                                          pos. of character in font
			canvas.DrawRect(x, y, font.fontDat.PeekInt((chrs[i]-32)*4*2 + 4), font.maxHeight, font.gfxFont, font.fontDat.PeekInt((chrs[i]-32)*4*2), 0, font.fontDat.PeekInt((chrs[i]-32)*4*2 + 4), font.maxHeight)
			x = x + font.fontDat.PeekInt((chrs[i]-32)*4*2 + 4)
		Next
 
	End
	
	Method stringWidth:Int(font:MyFont,text:String)
		Local len:Int = text.Length()
		Local chrs:Int[]
		Local length:Int = 0
		
		chrs = text.ToChars()
		
		For Local i:Int = 0 To len - 1
			'                                width of character in font
			length = length + font.fontDat.PeekInt((chrs[i]-32)*4*2 + 4)
		Next
		
		Return length
	End
		
End

Function Main:Int()
	New FontTest()
	Return 0
End

I’m a bit lost for words, but if you find my “poor man’s Font 2 PNG” useful, feel free to use this code.

Unlimited Objects Source Code

In my old blog post I gave some idea how to implement “unlimited objects” program. In the original video I used 16 canvases with 16 images + the actual visible canvas. Two canvases only is sufficient.

In the source (Cerberus X) below, no external graphics files are needed:

Import mojo2

Function Main()
	New MyApp
End

Class MyApp Extends App
	
	Field gfxCopy:Image[16]
	Field ccanvas:Canvas
	Field counter:Int
	Field angle:Float	
	Field canvas:Canvas
	
	Field scaleX:Float, scaleY:Float
		
	Field x:Float, y:Float
	Field r:Float
	
	Method OnCreate()
			
		canvas = New Canvas()
		counter = 0
		
		For Local i:Int = 0 To 15
			gfxCopy[i] = New Image(640,480,.0,.0)
		Next
		
		ccanvas = New Canvas(gfxCopy[0])
		
		scaleX = DeviceWidth / 640
		scaleY = DeviceHeight / 480
		
		r = 100
		SetUpdateRate(60)
	End
	
	Method OnUpdate()

	End
	
	Method OnRender()
		
		angle = angle + 2

		x = Cos(angle) * r + 640 / 2
		y = Sin(angle) * r + 480 / 2
		
		r = r + 0.1

		counter = counter + 1
		If counter = 16 Then counter = 0
				
		ccanvas.SetRenderTarget(gfxCopy[counter])
		ccanvas.SetColor(1,1,0)
		ccanvas.DrawCircle(x,y,32)
		ccanvas.SetColor(1,0,1)
		ccanvas.DrawCircle(x,y,30)
		
		ccanvas.Flush()
		
		canvas.PushMatrix()
		canvas.Scale(scaleX,scaleY)
		
		canvas.Clear	

		canvas.DrawImage(gfxCopy[counter],0,0)

		canvas.Flush()
		canvas.PopMatrix()
						
	End
	
End Class

The program gives different output, if the calculations are in OnUpdate() on HTML5 target.




Below is the old video I’ve made previously:

Source code license: MIT.

3D Stars As Lines

I must have been really tired when I coded & posted the old 3D stars codes… Anyway, here’s code for 3D stars as lines.

Below the video:

To get the stars drawn as lines is really simple. In the 2D world to draw a line we need x1, y1, x2 and y2. In the projection from 3D space, we simple add for example 4 to the z-coordinate of a point so that, the other point is further away and we get two points to the 2D world.

Below is the main part of the Monkey X source code:

		' Projection from 3D space to 2D screen
		For Local i:Int = 0 To STARS - 1
			Local x1,x2,y1,y2:Float
			
			z[i] = z[i] - 1
			If z[i] < 10 Then z[i] = Rnd(50,200)
						
			sx = x[i] / z[i] * 200 + 320
			sy = y[i] / z[i] * 200 + 240
			
			shade = 1 - z[i] / 200
			canvas.SetColor shade,shade,shade
			
			x1 = x[i] / z[i] * 200 + 320
			x2 = x[i] / (z[i] + 4) * 200 + 320
			y1 = y[i] / z[i] * 200 + 240
			y2 = y[i] / (z[i] + 4) * 200 + 240
			
			canvas.DrawLine(x1,y1,x2,y2)
			
		Next

For the end the source code in full:

Import mojo2

Function Main:Int()
	New MyApp
	Return 0
End

Class MyApp Extends App

	Const STARS:Int = 280
		
	Field x:Float[STARS],y:Float[STARS],z:Float[STARS]
	
	Field canvas:Canvas
	Field sx:Float, sy:Float
	
	Method OnCreate()

		For Local i:Int = 0 To STARS - 1
			x[i] = Rnd(-50,50)
			y[i] = Rnd(-50,50)
			z[i] = Rnd(50,200)
		Next
		
		canvas = New Canvas()
		
		SetUpdateRate(60)
	End

	Method OnUpdate()
						
	End
	

	Method OnRender()
		
		Local shade:Float
		
		canvas.PushMatrix()

		canvas.Clear()

		' Projection from 3D space to 2D screen
		For Local i:Int = 0 To STARS - 1
			Local x1,x2,y1,y2:Float
			
			z[i] = z[i] - 1
			If z[i] < 10 Then z[i] = Rnd(50,200)
						
			sx = x[i] / z[i] * 200 + 320
			sy = y[i] / z[i] * 200 + 240
			
			shade = 1 - z[i] / 200
			canvas.SetColor shade,shade,shade
			
			x1 = x[i] / z[i] * 200 + 320
			x2 = x[i] / (z[i] + 4) * 200 + 320
			y1 = y[i] / z[i] * 200 + 240
			y2 = y[i] / (z[i] + 4) * 200 + 240
			
			canvas.DrawLine(x1,y1,x2,y2)
			
		Next
	
		canvas.Flush()
		
		canvas.PopMatrix()
		
	End

End Class

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!

Tile Scrolling with Maps Made with my Map Editor

Little tutorial on scrolling a map/world made with my Map Editor.

First, the source code in full:

Import mojo2
Import brl

Function Main()
	New MyApp
End

Class MyApp Extends App

	Field canvas:Canvas
	Field gfxShapes:Image
	Field touchX,touchY:Float
	Field prevTX,prevTY:Float
	Field scaleX,scaleY:Float
	Field scrollX,scrollY:Float
	Field touchXD,touchYD:Float
	Field scroll:Bool
	Field map:Int[]
	Field worldHeight:Int, worldWidth:Int	
	
	Field mapX:Int
	Field mapY:Int
	
	Method OnCreate()
		canvas = New Canvas()
		

		gfxShapes = Image.Load("shapes.png")

		SetDeviceWindow(640,480,0)
		scaleX = DeviceWidth() / 640.0
		scaleY = DeviceHeight() / 480.0
		
		Local mapFile:=FileStream.Open("cerberus://data/map.dat","r")

		worldWidth = mapFile.ReadInt()
		worldHeight = mapFile.ReadInt()
		
		map = map.Resize(worldWidth * worldHeight)
		
		For Local i:Int = 0 To worldWidth * worldHeight - 1
			map[i] = mapFile.ReadInt()
		Next
			
		mapFile.Close()
		
		mapX = 0
		mapY = 0
		
	End
	
	Method OnUpdate()

		touchX = TouchX()
		touchY = TouchY()
										
		If TouchDown(0) > 0 Then
			
			scrollX = (touchX - prevTX)
			scrollY = (touchY - prevTY)
 			
			If Abs(scrollX) > Abs(scrollY) Then
				If scrollX < 0 Then mapX = mapX - 1 Else mapX = mapX + 1
			Else
				If scrollY < 0 Then mapY = mapY - 1 Else mapY = mapY + 1
			Endif
			
			If mapX < 0 Then mapX = 0
			If mapX > worldWidth - 40 - 1 Then mapX = worldWidth - 40 - 1
			If mapY < 0 Then mapY = 0
			If mapY > worldHeight - 30 - 1 Then mapY = worldHeight - 30 - 1

		Endif

		prevTX = touchX
		prevTY = touchY	

	End

	Method OnRender()
		canvas.PushMatrix()
		canvas.Scale(scaleX,scaleY)
		
		For Local y:Int = 0 To 30 - 1
			For Local x:Int = 0 To 40 - 1
				canvas.DrawRect(x * 16, y * 16, gfxShapes, 0, map[mapX + x + (mapY + y) * worldWidth] * 16, 16, 16)
			Next
		Next

		canvas.Flush()
		canvas.PopMatrix()
	End
	
End Class

Quite straight forward, but some words about the code.

In the Map Editor dat-file, the first 4 byte integer declares the width of the map, the second the height of the map in tiles. The size of the map is read first, then the map itself.

The scrolling is made with touch screen in mind.

The meaning of the Abs(…)-sentence is, that in which direction in the touch screen the finger is being moved most and then the map is scrolled into that direction.

The 256 color shapes of the world are from an Ultima IV remake and are free to be used. The original project is “xu4”, if my memory servers me right.

The source above is places to public domain as license for it.

Please, if you make a game (in any programming language) utilizing my code, show me, what you have achieved. I’m big fan of games of this kind of genre.

 

For the end a video regarding this post. At the beginning of the video there’s some scrolling:

 

 

Embedding HTML5 output of Cerberus X to WordPress pages

The first thing you need is Code Embed plugin.

If your HTML5 output code loads files, something must be changed in the JavaScript-code. Find the following piece of code:

BBHtml5Game.prototype.PathToUrl=function( path ){
	if( path.indexOf( "cerberus:" )!=0 ){
		return path;
	}else if( path.indexOf( "cerberus://data/" )==0 ) {
		return "data/"+path.slice( 16 );
	}
	return "";
}

The URL of the data drawer must be changed. If you have the data drawer at the root of your www (public_html) drawer, change the “path.slice” line like this:

return "/data/"+path.slice( 16 );

If you’re working offline with some server program and have a testsite to experiment with, the path can be found as follows:

return "http://localhost/testsite/data/"+path.slice( 16 );

The y-coordinate of the mouse need also some adjustment, if the page has scrollbar: The y-start depends on the position of the scrollbar.

Find the following function:

	function mouseY( e ){
		var y=e.clientY+document.body.scrollTop;
		var c=canvas;
		while( c ){
			y-=c.offsetTop;
			c=c.offsetParent;
		}
		return y*yscale;
	}

The y-coordinate is correct with following change:

function mouseY( e ){
		var scrollTop = (window.pageYOffset !== undefined) ? window.pageYOffset : (document.documentElement || document.body.parentNode || document.body).scrollTop;
		var y=e.clientY+document.body.scrollTop + scrollTop;
		var c=canvas;
		while( c ){
			y-=c.offsetTop;
			c=c.offsetParent;
		}
		return y*yscale;
	}

With the touch screen no additional changes need to be done.

While working with WordPress, the “tool/status” bar of WordPress changes the y-coordinate too, but the visitor on your page doesn’t have that page with the “tool/status” bar of WordPress. 🙂

You’ll probably want to remove the console from the page, too. Just remove all the references to splitter and console from the CerberusGame.html.

I almost forgot, in CerberusGame.html use absolute path to find the JavaScript-file. For example src=”https://yoursite.com/drawer/program.js”. Perhaps at first is good practice to try with all the contents of the default CerberusGame.html, so that you see that everything is working.

This should help.

As an example in practice, you might want check my online games corner.

Good luck!

Old School XII – Unlimited Objects

The idea to Old School XII comes from Amiga demos from the early 90’s. First there was lots of competition in the Amiga demo scene on who makes a demo with most amount of bobs (blitter objects) in one 50Hz frame. Eventually we saw bob demos with unlimited amount of bobs!

The amount of bobs is basically unlimited; only the visible area of the screen limits the amount of moving bobs. This is achieved with actually only one bob!

I made today this effect in Monkey X.

The implementation in Monkey X is done by using multiple canvases with images. One canvas is used to draw into screen, the rest of of the canvases are used to achieve the unlimited objects effect.

Below is the video of the Monkey X implementation:

I haven’t yet tested if less amount of canvases is sufficient, but in the beginning of the code I wrote the following:

		For Local i:Int = 0 To 15
			gfxCopy[i] = New Image(640,480,.0,.0)
			ccanvas[i] = New Canvas(gfxCopy[i])
		Next

The only object is drawn subsequently to each of created canvases. The following line does the magic of unlimited objects:

canvas.DrawImage(gfxCopy[counter],0,0)

For the end below is one Amiga demo with unlimited bobs:

I made HD (or HQ) version of the video later today:

That’s all for now!

Touching an Image in Cerberus X

This post is the 3rd in the series of touching an image pixel accurately. The second one is too complicated, now I have kept it clear and simple.

The image to be touch is middle handled (this makes scaling easier) and the image both moves and is scaled real time.

Here’s the source code:

Import mojo2
Import opengl.gles20

Function Main()
	New MyApp
End


Class MyApp Extends App
	
	Const WIDTH:Float = 80
	Const HEIGHT:Float = 80

	Field canvas:Canvas
	
	Field gfxBG:Image
	Field gfxBall:Image
	Field BallData:DataBuffer
	
	Field scaleX:Float, scaleY:Float
	Field scale:Float
	Field touchX:Float, touchY:Float
	Field angle:Float
	Field x:Int, y:Int
	Field hit:Bool = False
	
	Method OnCreate()
		
		SetDeviceWindow(800,600,0)
		
		canvas = New Canvas
		
		scaleX = DeviceWidth() / 800.0
		scaleY = DeviceHeight() / 600.0

		gfxBG = Image.Load("bg.jpg",0,0)
	    gfxBall = Image.Load("ball.png")	' By default this image is middle handled ("ball.png",.5,.5)

		' Information of "ball.png" image is loaded here
	    BallData = LoadImageData("cerberus://data/ball.png") ' If you're using Monkey X, change cerberus to monkey
		
		SetUpdateRate(30)
		
	End
	
	Method OnUpdate()

		Local coordX:Float, coordY:Float
	
		
		scale = 3 - Cos(angle * 4)	' calculate scaling factor to the image
		angle = angle + 2

		x = 800 / 2 + Cos(angle) * 150
		y = 600 / 2 + Sin(angle) * 150

		If TouchDown(0) > 0 Then
			hit = False
		
			touchX = TouchX()
			touchY = TouchY()
				
			' The image is middle handled
			' Here we find the "virtual" (=scaled) top left corner
		
			coordX = x - (WIDTH / 2) * scale
			coordY = y - (HEIGHT / 2) * scale

			' Is the object touched at its rectangle?
			If touchX - coordX < WIDTH * scale And touchX - coordX > 0 And touchY - coordY < HEIGHT * scale And touchY - coordY > 0 Then
		
				Local pointX:Int
				Local pointY:Int
				Local data:Int
			
				' In the actual touch test we check the original image;
				' that is why following "scaling" must be done for the touch point
				pointX = Int((touchX - coordX) / scale)
				pointY = Int((touchY - coordY) / scale)

				data = BallData.PeekInt(pointX * 4 + pointY * WIDTH * 4) & $FF000000
			
				' If alpha <> 0 there are pixels
				If data <> 0 Then hit = True Else hit = False
			Endif
		Endif
	End

	Method OnRender()

		canvas.PushMatrix()
		canvas.Scale(scaleX,scaleY)
		canvas.SetBlendMode(BlendMode.Alpha)
		canvas.DrawImage gfxBG,0,0
		
		If hit = True Then canvas.SetBlendMode(BlendMode.Additive) Else canvas.SetBlendMode(BlendMode.Alpha)

		canvas.DrawImage(gfxBall, x, y, 0, scale, scale)
		
		canvas.Flush
		canvas.PopMatrix
		
	End

End Class

The actual test is made for the original image data, that is left intact. Because the image is middle handled in order to get the top left corner of the image, one must decrease half of the width and height of the image from the x, y of the image. But as the image is scaled the actual graphical top left corner is x – (width / 2) * scale and y – (height / 2) * scale.

When then top left corner of the rectangle is calculated, to this is added the scaled size: width * scale and height * scale. This is taken care of in the if-sentence, when checking if in the rectangle is touched.

When one has the touching point, the point in the image must be “scaled” by the scale factor, see the commented part of the code for this.

In the actual test is tested is the picture’s alpha value in the calculated point <> 0; if it is, the image that has transparent pixels, must have been touched.

Clear and simple. 🙂

Below is a video of regarding this post:

If you want to compile this in Monkey X, just change in the LoadImageData-part “cerberus” to “monkey”.

Update:

In my Memorable Melodies  game is used slightly different code to touch the images, because the images to be touched don’t have “holes”.

Snowing Effect in Monkey X

Since Christmas is coming soon, I decided to share my snowing effect code I wrote last year. The original code was written in BlitzMax. This year I have already made new Christmas intro in Monkey X. You may want to take look at the snowing effect of the Christmas video of the last year.

Import mojo2

Function Main()
	New MyApp
End

Class snowFlake
	Field x:Float, y:Float
	Field dx:Float
	Field r:Int
	Field yspeed:Float
	Field flakeAngle:Float
End Class

Class MyApp Extends App

	Field gfxBG:Image
	Field canvas:Canvas
	
	Global flakeList := New List<snowFlake>
	
	Method OnCreate()

		SetDeviceWindow(640,480,0)		
		canvas = New Canvas
		
		gfxBG = Image.Load("bg.jpg",.0,.0)
			
		For Local i = 0 To 149
			Local flake:snowFlake = New snowFlake
			flake.x = Rnd(50,640-50)
			flake.r = Rnd(2,8)
			flake.y = -flake.r * 2
			flake.yspeed = Rnd(0.7,3)
			flake.flakeAngle = Rnd(0,359)
			flakeList.AddLast(flake)
		Next
		
		SetUpdateRate(30)
		
	End
	
	Method OnUpdate()
		
	End
	
	Method OnRender()
		
		canvas.PushMatrix()
		canvas.Scale(DeviceWidth() / 640.0, DeviceHeight() / 480.0)
		canvas.SetAlpha 1
		canvas.SetBlendMode(BlendMode.Opaque)
		canvas.DrawImage(gfxBG,0,0)
		
		For Local flake:snowFlake = Eachin flakeList
		
			flake.x = flake.x + flake.dx
			flake.y = flake.y + flake.yspeed
			
			canvas.DrawCircle flake.x, flake.y, flake.r
			flake.dx = Cos(flake.flakeAngle) * 4 * Rnd(0.2,1)

			If flake.y >= 480 + flake.r * 2 Then
				flake.r = Rnd(2,8)
				flake.y = -flake.r * 2
			Endif

			flake.flakeAngle = flake.flakeAngle + 1
		
		Next
		
		canvas.PopMatrix()
		canvas.Flush()

		
	End
	
End Class

Examine the code and you’ll get the idea quickly. Implementation in other programming languages should be quit straight forward. Just use background picture of your own.

Feel free to use the code.

Screenshot of the program:

I will soon publish my new Merry Christmas 2017 and Happy New Year 2018 video. And… It’s also written in Monkey X.