About Monkey 2 › Forums › Monkey 2 Programming Help › Draw image
This topic contains 31 replies, has 6 voices, and was last updated by 
 juliocmfj 1 year, 7 months ago.
- 
		AuthorPosts
 - 
		
			
				
August 31, 2017 at 5:18 pm #10146
I am curious, Why did you decide to use Unsigned Int?
August 31, 2017 at 7:12 pm #10147Why there is no tile with negative ID. So I found it unnecessary to use an Int.
August 31, 2017 at 7:28 pm #10149And it should. I also don’t get why using an int instead of an unsigned should make trouble in that case. It simply doesn’t make sense at all.
August 31, 2017 at 7:38 pm #10150I’m trying to understand by now why this happened. If I was drawing based on Int coordinates and not UInt. UInt is serving exclusively only to get the ID of the tiles, and nothing more. But… That’s it.
August 31, 2017 at 10:16 pm #10151I recommend avoiding the use unsigned values unless you are dealing with binary ‘bit patterns’ (for example, 32 bit ARGB values) or extern APIs that use unsigned values.
The main problem is that math works differently with unsigned, which can lead to unexpected/surprising results. For example, unsigned numbers can never be <0 as they’re always positive so you can run into trouble ‘looping backwards’ quite easily. Also, subtracting an unsigned number from any other integer will always give you an unsigned result (ie: >=0 ) as both are converted to unsigned before the subtraction.
Even if you expect values to always be >=0, eg: the layerId variable above, I would still recommend using plain old Int just to minimize the chance of surprises. I would not expect there to be any practical use for unsigned in the stuff you are doing here. Just because a feature is there doesn’t mean you have to use it!
Unsigned can be useful for dealing with bit masks an so on, but it should be used very sparingly IMO.
August 31, 2017 at 10:34 pm #10152Roger, Mark. I will be more cautious when using unsigned values. I’ll make the necessary changes to the code right now. And again, thanks for the explanation.
September 1, 2017 at 5:46 am #10175I’ve been trying to do some optimizations. I rendered a 1000×1000 map with 48×48 tiles and FPS in release mode averaged 10 FPS.
After the optimizations, I got the average between 55 and 60 FPS with the same gigantic map.
Below is the code. I would like opinions and know if I made a mistake.
Monkey1234567891011121314151617181920212223242526272829303132' BEFOREMethod Render(canvas:Canvas, layerId:Int)For Local y:Int = 0 Until layers[layerId].heightFor Local x:Int = 0 Until layers[layerId].widthIf (layers[layerId].map[x, y] > -1)Local tile:TiledTile = New TiledTile()tile.image = tileArray[layers[layerId].map[x, y]].imagetile.xy = New Vec2f(layers[layerId].x + x * tileWidth, layers[layerId].y + y * tileHeight)If (tile.xy.X > -tileWidth And tile.xy.X < canvas.Viewport.Width And tile.xy.Y > -tileHeight And tile.xy.Y < canvas.Viewport.Height)canvas.DrawImage(tile.image, tile.xy.X, tile.xy.Y)EndEndNextNextEnd' AFTERMethod Render(canvas:Canvas, layerId:Int)For Local y:Int = 0 Until layers[layerId].heightFor Local x:Int = 0 Until layers[layerId].widthIf (layers[layerId].map[x, y] > -1)Local xy:Vec2f = New Vec2f(layers[layerId].x + x * tileWidth, layers[layerId].y + y * tileHeight)If (xy.X > -tileWidth And xy.X < canvas.Viewport.Width And xy.Y > -tileHeight And xy.Y < canvas.Viewport.Height)Local tile:TiledTile = New TiledTile()tile.image = tileArray[layers[layerId].map[x, y]].imagetile.xy = xycanvas.DrawImage(tile.image, tile.xy.X, tile.xy.Y)EndEndNextNextEndSeptember 1, 2017 at 6:10 am #10176Working with constant-sized tiles grid you can calculate starting and ending indexies for x and y outside of double for-for.
Then your ‘for’ loops will go through visible tiles only.
September 1, 2017 at 6:18 am #10177Did not quite understand. Would you have a simple example?
September 1, 2017 at 6:31 am #10178Pseudocode:
Monkey12345678910111213141516Method Render(canvas:Canvas, layerId:Int)Local xStart := [calculate x-index for first visible tile accordingly to x-offset]Local yStart := [calculate y-index for first visible tile accordingly to y-offset]Local xEnd := xStart + viewport.width / tileWidthLocal yEnd := yStart + viewport.height / tileHeightFor Local y := yStart To yEndFor Local x := xStart To xEndIf layers[layerId].map[x, y] = -1 ContinueLocal xy:Vec2f = New Vec2f(layers[layerId].x + x * tileWidth, layers[layerId].y + y * tileHeight)Local image := tileArray[layers[layerId].map[x, y]].imagecanvas.DrawImage(image, xy.x, xy.y)NextNextEndNote:
- inside of FOR I removed check for visibility because now we go through visible tiles onle
 - also I removed creating New TiledTile() – why to create instance if we can just draw ‘plain’ image
 - also I replaced xy.X & xy.Y with xy.x & xy.y – because of access to fields (small chars here) is faster that to properties (properties equals to method call)
 
September 2, 2017 at 8:36 am #10204Primitives are faster than struct fields.. So I would not use vec2 inside such loops.
Here I use vx ans vy but you Can also put their expressions direcly in drawimage arguments.
The image coule be passed direcly too, it might perform better.[/crayon]Monkey123456789101112131415161718192021[crayon-5cb9c1a61665d981167373 inline="true" ]Method Render(canvas:Canvas, layerId:Int)Local xStart := [calculate x-index for first visible tile accordingly to x-offset]Local yStart := [calculate y-index for first visible tile accordingly to y-offset]Local xEnd := xStart + viewport.width / tileWidthLocal yEnd := yStart + viewport.height / tileHeightLocal vx : FloatLocal vy : FloatLocal image : ImageFor Local y := yStart To yEndFor Local x := xStart To xEndIf layers[layerId].map[x, y] = -1 Continuevx = layers[layerId].x + x * tileWidthvy = layers[layerId].y + y * tileHeightimage = tileArray[layers[layerId].map[x, y]].imagecanvas.DrawImage(image, vx, vy)NextNextEndSeptember 3, 2017 at 12:49 am #10219abakobo, I followed your recommendations as well.
September 3, 2017 at 1:09 am #10220Now you have a part that I do not understand. In the map matrix, the value -1 corresponds to no tiles, that is, no tiles with this value will be rendered, just above it.
I saw above, what you did:
Monkey1If layers[layerId].map[x, y] = -1 Continue. I think that this way, it should render the tiles only value -1… What whould be the logic behind?
September 3, 2017 at 2:25 am #10222Keyword ‘Continue’ inside for loop is equivalent of Next, i.e. immediately go to the next loop frame. And here – skip all with index -1.
September 3, 2017 at 2:48 am #10223It would be the same as:
Monkey123If (layers[layerId].map[x, y] > -1)' DrawEnd - 
		AuthorPosts
 
You must be logged in to reply to this topic.