Fps down while rendering a tilemap

Monkey Forums/Monkey Programming/Fps down while rendering a tilemap

Josepho(Posted 2012) [#1]
Hi there, me again, hehe

I have been making some testings in monkey and i tried to load a tilemap that is 18x14 tiles of 48x48 pixels each

Main render code consists in a draw image that selects the right frame and puts the tiles in its correct position

Problem is, I not able to reach the 60fps in the html5 and i didnt even reach 25fps in the flash version, counting that my computer is new.

Why monkey has this performance problems? I dont understand, i am making something wrong?


Jesse(Posted 2012) [#2]

Why monkey has this performance problems? I dont understand, i am making something wrong?



with out the source code, we can only guess.
html5 has different performance with different browser. html5 is in the optimization stage. some browsers are hardware accelerated and some are not so results will vary.

my game "SURVIBALL" I have here works great in flash and html5. I have it running at 30fps is really smooth and I am using 32x32 tile size with a backdrop effect and a bout 100 particles at a all times.

This only leads me to believe that you are doing something wrong and with out the code there is not much we can help you with.

Also don't expect flash and html to work as fast as an executable. That's not Monkey's fault.


Shinkiro1(Posted 2012) [#3]
Are your tiles in 1 image or in separate images?
If they are in separate images -> copy all tiles into 1 image and then use GrabImage() to get your tiles
If in 1 image -> it's not easy to tell what's going wrong without looking at the code

But I can assure you that you are doing something wrong, monkey can easily handle your requirements :)


dave.h(Posted 2012) [#4]
I've just started one that's similair in specs to yours and my first trial runs come in at 115 fps on html5 and my pc is 6 years old also they are in seperate images which is slower


Josepho(Posted 2012) [#5]
Here is my draw code
	Method draw(_x:Int, _y:Int)		
		Local idChangerX:Int = Floor (cameraX / tileSizeX)
		Local moverX:Int = cameraX - (idChangerX * tileSizeX)
		Local idChangerY:Int = Floor (cameraY / tileSizeY)
		Local moverY:Int = cameraY - (idChangerY * tileSizeY)
		
		visorX = idChangerX
		visorY = idChangerY
			
		For Local iFila:Int = visorY to visorY + visorSizeY
			For Local iCol:Int = visorX to visorX + visorSizeX
				if ((iFila >= 0) And (iCol >= 0) And (iFila <= sizeY) And (iCol <= sizeX))
					Local value:Int = arrayTiles.ToArray [getPos(iCol, iFila)]
					if (value > -1) Then DrawImage(img, x + _x + cameraX - moverX + ((iCol-visorX) * tileSizeX), y + _y + cameraY - moverY + ((iFila-visorY) * tileSizeY), value)
				EndIf
			Next
		Next
	End


Any ideas? It has no sense :(


slenkar(Posted 2012) [#6]
arrayTiles.ToArray

this is your slowdown probly

why not just keep it as an array


or you could put arrayTiles.ToArray before the big double FOR NEXT loop

also check getPos to make sure it doesnt do anything slow


Jesse(Posted 2012) [#7]
how are you loading the images? are they all in one sprite?
are you using "GrabImage" to parse the sprites? ( I would recommend it)
if you can, do a frame rate speed test on the draw method to see how long the draw function takes to execute:
local start:int = Millisecs()
map.Draw()
Drawtext (millisecs() - start), 100,10 


that should give you an idea how long it's taking to draw the map.

[edit]
LOL!

yea, arraytiles.ToArray for every tile is killing your performance. taking it out of the loop should improve the performance a lot.

why not just keep them in an array?


Josepho(Posted 2012) [#8]
It worked! Many thanks, I didnt expect that function was so slow


Josepho(Posted 2012) [#9]
Bump for justice

I made a new test, same code (without the list, now working directly with arrays) in the flash version if you add a scale(0.5,0.5) at the beginning of the loop the frames slows down a lot only on the flash version :(

Html5 and Android went perfect, only problem is flash..

Is there anyway to fix it??


Samah(Posted 2012) [#10]
Edit: I see monkey.List also has a ToArray() method, so I assume you are using that.
----------------
Is arrayTiles an ArrayList? ToArray creates a new array object on every call (unavoidable) which will be killing your performance.

What you can do is use FillArray instead. You pass an existing array and it will populate it. It will return an integer representing the number of elements that were actually populated (if your array is bigger than the size of the list).

[monkeycode]Field myArray:Object[]
...
If myArray.Length < arrayTiles.Size Then
myArray = New Object[arrayTiles.Size*2]
End
Local count:Int = arrayTiles.FillArray(myArray)[/monkeycode]
----------------

How are you resetting the Scale? You should be wrapping that loop in a PushMatrix/PopMatrix pair.

[monkeycode]PushMatrix
Scale(0.5, 0.5)
' your big loop here
PopMatrix[/monkeycode]


therevills(Posted 2012) [#11]
Are you compiling to release mode or debug mode?


Josepho(Posted 2012) [#12]
Hi samah, im not using lists now this time is an array from the beginning so im not longer using the ToArray() method

I am using the pushmatrix popmatrix functions too and the fps still being low

And Therevills, im using release mode

Has the flash version problems with the scale function?


therevills(Posted 2012) [#13]
Normally Flash is faster than HTML5... Can you show us you code?


Josepho(Posted 2012) [#14]
Ok here it is

TileMap drawing function

	Method draw(_x:Int, _y:Int)		
		Local idChangerX:Int = Floor (FP.camera.x / tileSizeX)
		Local moverX:Int = FP.camera.x - (idChangerX * tileSizeX)
		Local idChangerY:Int = Floor (FP.camera.y / tileSizeY)
		Local moverY:Int = FP.camera.y - (idChangerY * tileSizeY)
		
		visorX = idChangerX
		visorY = idChangerY
			
		For Local iFila:Int = visorY to visorY + visorSizeY
			For Local iCol:Int = visorX to visorX + visorSizeX
				if ((iFila >= 0) And (iCol >= 0) And (iFila < sizeY) And (iCol < sizeX))
					Local value:Int = arrTiles [getPos(iCol, iFila)]
					if (value > -1) Then DrawImage(img, x + _x + FP.camera.x - moverX + ((iCol-visorX) * tileSizeX), y + _y + FP.camera.y - moverY + ((iFila-visorY) * tileSizeY), value)
				EndIf
			Next
		Next
	End


getPos function
	Method getPos:Int(_x:Int, _y:Int)
		Return ((_y * sizeX) + _x)
	End


And draw function of the room that contains the scale
	Method drawEntities()
		PushMatrix
		
			Scale(FP.camera.zoom, FP.camera.zoom)
			
			if (FP.camera.rotation) 
				Translate(DeviceWidth/FP.camera.zoom,0)
				Rotate(-90)
			EndIf
			

		For Local inst:instance = eachin entities
			inst.drawInstance()
		Next
		
		PopMatrix
	End


Draw instance calls to the instance calling method and the coli drawing methods
	Method drawColisions()
		SetAlpha(0.2)
		For Local hit:hitBox = eachin arrayMask
			DrawRect(x + hit.x - FP.camera.x, y + hit.y - FP.camera.y, hit.w, hit.h)
		Next
		
		For Local hit:hitCircle = eachin arrayCircs
			DrawCircle(x+hit.x-FP.camera.x, y+hit.y-FP.camera.y, hit.r)
		Next
		SetAlpha(1)
	End
	
	Method drawInstance ()
		
		For Local auxImg:jImage=eachin arrayImg
			auxImg.draw(x - FP.camera.x, y - FP.camera.y)
		Next
		
		drawColisions()
	End


Also the rendering in flash has some bugs that the html5/android version doesnt have



Shinkiro1(Posted 2012) [#15]
A good way to start is to know where the most time is spent.
[monkeycode]
Local ms:Int = Millisecs()
' YourCode
Print ("Time: " + (Millisecs()-ms))
[/monkeycode]


therevills(Posted 2012) [#16]
So if you remove the scale command it improves the FPS?

Can you try it without drawing the collisions (in built draw functions are slow)?

And with your graphics defects, try drawing them as an Int:
[monkeycode]if (value > -1) Then DrawImage(img, Int(x + _x + FP.camera.x - moverX + ((iCol-visorX) * tileSizeX)), Int(y + _y + FP.camera.y - moverY + ((iFila-visorY) * tileSizeY)), value)[/monkeycode]


Josepho(Posted 2012) [#17]
If I remove the scale command improves the FPS, yup, and if i add the ints to my code doesnt fix the graphics defects

The zoom in the screenshot is set to 0.66


Grey Alien(Posted 2012) [#18]
Flash can't scale bitmaps for sh*t. Nor rotate them or even alpha blend them very fast. At least that was the case when we were making a Facebook game and using Flash 9 as our target version. Perhaps the new versions with hardware acceleration are better although you can't guarantee users have them.


Josepho(Posted 2012) [#19]
Flash has speed ways to archieve this, i already archieve the same thing im trying to make in monkey flash by using flashpunk

So flash can do it, but monkey flash exporter doesnt
I think i will drop the flash develop in monkey :(

The camera in this demo is ported x2, in the demo i try to compile with monkey the camera is ported x0.66


CGV(Posted 2012) [#20]
I bought Monkey for Flash development and as a way of future proofing myself against Adobe's apparent intent to kill off Flash but I ended up going back to Flixel for my Flash development.

Monkey's Flash target just isn't up to snuff. I'm guessing Mark didn't thoroughly research Flash before writing Monkey's Flash target. He needs to take a look at how Flixel and Flashpunk do it.

Please, Mark, take a look!!!!


slenkar(Posted 2012) [#21]
Have you tried turning off image filtering in flash?
(in the config.txt file in the build folder)


Josepho(Posted 2012) [#22]
Slenkar, tried, i reach 40 fps making that, better than before but still very slow


Neuro(Posted 2012) [#23]
Out of curiosity, what are you guys using to build the tile maps?


golomp(Posted 2012) [#24]
i tried several (beautiful) but i lose time to find trick to make this or that
so i build my (hugly) own.
:)


Josepho(Posted 2012) [#25]
Neuro im using my own tool called Qtile, maybe someday i will release it






Neuro(Posted 2012) [#26]
Thanks Josepho, looks interesting and would be another nice toolset to use with monkey if you decide to release it. I'm currently using Tiled for my project.


Josepho(Posted 2012) [#27]
So i have to drop the flash version of the project in monkey?

Would be mark interested on watching the advice of CGV and take a look on how flashpunk and flixel archieves this speeds?

Hello, mark? hehe


AdamRedwoods(Posted 2012) [#28]
Updating code at 60fps takes a bit of toll on non-graphic routines as well.
My game here, runs ok at 30fps, but starts to chunk at 60fps (on flash 11, 1024x600px, game is 15fps):


I took a quick look at flashpunk and flixel, and they are doing about the same thing as monkey mojo is doing... EXCEPT the former two have dedicated tile drawing routines, which are straight copyPixel routines (no scaling, no alpha) vs. Bitmap.Draw routines. If the tilemap is an atlas, then my guess is they resize the atlas once, cache it, and copypixel from that. I know for a fact that monkey mojo does NOT have the ability to resize and cache bitmaps.

My game above does a ton of scaling (which is a known slowdown for me), but a note is that Android runs just as slow as the Flash version, which I do find odd. So yes, if your game MUST run at 60fps on Flash, then you may need a different library.

Another path however, if you know Actionscript well, you could create your own dedicated Actionscript tilemap renderer, and Import it as an external library within monkey.