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 placed to public domain as a license.

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&#8221;. 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.

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!

My First Android Game Published on Google Play

This game project started in the year 2015. A long time passed I’m doing nothing for the game, but finally its ready and published!

The project started with Monkey X, but I finished it with Cerberus X and compiled it to Android. I have not — at least not yet — plans for a free PC version.

Before publishing I ran the tests that Google offers for the app. My app passed with zero crashes. 🙂

You might want to take a look at the game played with PC in the video above.

Like I wrote in “Shorty about computer playing history” post, if I’m ever to create a game, it would always have an ending and so does this game have.

The game is free (no ads) you might want to try it with your Android device, search for “Memorable Melodies” on Google Play. Or get here:

I hope you like it!

Starfield cube 2 and other Blitz3D demos

I haven’t done much 3D programming in Blitz3D. You can achieve quite a lot with a small effort with it. Also in Monkey2 programming language is the main functionality of Blitz3D. The idea to program a starfield cube came from an Amiga remix tune, that has speech in it: ”Starfield in a box. OMG it is rotating!” Back in the time it was hard to program things like that in assembly on Amiga. Nowadays even I can put a code together, that does the job in Blitz3D.

Starfield cube 2:

Making the starfield cube 2 program made me to create also the following video as a result of inspiration with Blitz3D:

The tiger in the cube (in some parts of the video) is from a photo of my trip to Zoo of Helsinki (Korkeasaaren eläintarha). The tiger seemed to be a bit stressed while people were watching it. Though, I remember someone saying it’s smart, because it uses the same always the same paths, when walking.

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

New year, new programming language

Blow from the past… Cerbeus X programming language is based on Monkey X, and has dedicated community behind it. With quick look to the language, it seems that fonts are handled in a different way, more advanced way.

Below is Old School XI demonstration made in Cerberus X.

I changed the colors a bit and had to change the light position to a positive value, rest goes like in good old Monkey X programming.

You’ll probably see here some Cerberus X tutorials in the future and practically all my Monkey X tutorials help you to get started with Cerberus X. Stay tuned! 🙂

Let’s have a great year!

Merry Christmas and Happy New Year 2018

Blue Bit Entertainment wishes you all Merry Christmas and Happy New Year 2018!

The intro in the video is coded in Monkey X.

Today is a good day wish merry Christmas, since today is Lucia day, that is also a Swedish tradition that lives here in Finland too. The day is related to Sancta Lucia. Lucia was a saint who was born in the year 283.

It’s been a hard year; so much more I would wanted to give to Blue Bit Entertainment… Eventually in the summer bad insomnia troubled me that seems to be behind now…

I’m trying to publish version 1.02 for both Order the Chaos and Order the Chaos II before 24th December. Let’s see, if I’m able to do that…

Perhaps next year finally my first Android game sees the daylight. I’ve plans for an Android app too… A life long project (well, kind of) that would get updates in order to get more and more features…. Hopefully the updates won’t be needed for any bug fixes… 🙂

Anyway, Merry Christmas 2017 and Happy New Year 2018!

 

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.

What if Smart Screen blocks my product?

What if Smart Screen prevents my product to run on your computer? You can check the file before running it with some antivirus scanner and as you see, that there’s nothing harmful, just run the program. See the video (I have Finnish system, but I have added needed translations):

In case you ran into any problems, just contact me by e-mail and we’ll find a solution together.

Image courtesy of TAW4 at FreeDigitalPhotos.net

At the time I’m writing this update to this blog post, I’m pleased to say that I have the OV code signing certificate for Windows. This doesn’t prevent the smart screen at first, but in time it may, if the product gets enough downloads.