Professional-Hobo / PokeMMOn-Old

MMO Pokemon Game using Node.js
http://keitharm.me/projects/pokemmon/
6 stars 2 forks source link

Render map using secondary canvas #55

Closed keitharm closed 8 years ago

keitharm commented 8 years ago

This is an experimental idea that could potentially make rendering much smoother and less processor intensive. Currently, the new tile render engine renders all of the tiles in the viewport based off of json data and then it keeps doing this at 60 fps. This is very taxing on the CPU, especially when the player moves and it has to offset all the tiles by a certain amount. What I propose is is to render the whole entire map on the separate canvas and then use draw image to draw that secondary canvas onto the primary canvas by the offset specified in the X and Y coordinates.

If we look at the performance of the old render engine that actually used a full background image to render on the canvas, it was about four times faster than the new tile rendering engine. So this new technique should have positive results since it would be generating the image completely on the first time and then it would just be copying from the secondary canvas without having to re-stitch the tiles together.

keitharm commented 8 years ago

Will be done using method 3: http://jsperf.com/copying-a-canvas-element

keitharm commented 8 years ago

Implemented and it works, but there is a race condition issue that needs to be solved...

keitharm commented 8 years ago

I just thought of a problem that this new technique may cause.

We originally moved over to the tile rendering engine in the 1st place so that mobile phones and crappy browsers that can't suppose large canvas images would be able to support the game. Since it'd only be drawing the tiles within the viewport, every device would be able to handle it (CPU intensive issues being disregarded).

However, this new rendering engine would require us to draw the entire map on a secondary canvas once and then using that secondary canvas as the source for the primary canvas to use when it does drawImage. So if the image is too big for the secondary canvas to render, nothing will happen - the same problem that we were experiencing with the 1st technique.

Some possible solutions would be drawing parts of the full image on multiple canvases, and then using drawImage appropriately with the primary canvas so that all X # of canvases move together and are stitched properly together. Sounds pretty daunting and I have no idea how CPU intensive it'll be, but it's a possible solution for now. Will look more into it.

keitharm commented 8 years ago

Ok so I've though of two possible solutions.

As I was saying before, we could split the main map up into a bunch of quadrants and then have 4 rendering quadrants for each corner (Top left & right and bottom left & right). This however looks like it'll be pretty difficult calculating which quadrant to render on which canvas depending on player position.

Another idea that would actually be very easy to implement however possibly CPU intensive would be to render all of the quadrants at once on a bunch of different canvases, and then have them all be rendered on the primary canvas using drawImage. If I remember correctly, Canvas is pretty memory efficient for things that are being drawn offscreen so this could possibly work, be memory efficient, and easy to implement.

Option 1 with 4 corner quadrants that use complex algorithms that will be CPU intensive everytime a new quadrant has to be loaded is good quality but will take a ton of time to implement and cost a lot because of the frappuccinos I'll have to drink.

Option 2 with many many quadrants would be CPU intensive only at the start since everything will have to be rendered but after that, it should be pretty smooth. The quality will likely not be as good as the 4 quadrant method, but it'll be trivial to implement and not require a ton of frappunccinos.

I am gonna try to implement option 2 tonight to see what the performance is like and if it'll be a viable solution.

lobabob commented 8 years ago

Sounds good to me. Add a task (quadrant optimization task) and a branch for it.