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

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()
		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
	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

	Method OnRender()

		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)

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”.


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

%d bloggers like this: