JavaScript - Drawing objects off the screen and other game optimizations - javascript

In my game a large map exists, and I am wondering if not drawing shapes (average 250+ at a time) when the player cant see them would make any difference in the game's performance.
Also, every frame I am checking the distance of the player to about 500+ other position vectors (used for enemies, food, bullet interactions), which takes a lot of square rooting. If I make a raw estimate just using the X and Y components combined, would that significantly boost game performance?

The only way to answer these questions is to try it and see what happens. You have to weigh the cost of calculating whether something is on the screen against the cost of drawing it. Again, you're going to have to measure both and decide for yourself.
As for measuring distance, you could try using the distance squared to avoid the square root.
Or you could try storing your objects in a data structure like a quadtree, which allow you to you only check the distance of nearby objects. Or putting it simpler: do you really need all 500 vectors active all of the time? Why not store them and only activate them when you need them?
But again, the only way to answer your question is to try it. We can't tell you whether this will vastly improve performance in your game. Only you can answer that, by trying things out. Good luck.

Related

JavaScript canvas game development

Ive been having a really baffling slow down issue with the game I am working on probably because I am unsure how to handle graphics (most likely responsible for the slow down) in javascript without using a third party framework like Phaser/ImapactJS/EaselJS etc)*. The following is the low down on how I am approaching my graphics. I would be very thankful for some tips or methods on how to do this right.
My game is tile based - using tiles designed at 500x500 px because I want them to display decently on high definition devices.
I am using a spritesheet to load all (most of) my tiles before the main loop is run. This image is roughly 4000 x 4000 (keeping it below 4096 because the GPU cant handle texture sizes larger than that).
I then use the drawImage function to cycle through and draw each tile on a part of the canvas using information (w, h, x, y) stored in the tile array. I do this on every cycle of the main loop using my drawMap function.
The map is currently 6x6 tiles in size
A character spritesheet is also loaded and drawn on to the canvas after the map has been drawn. The character displays a different frame of the animation on every cycle of the main loop. There are sets of animations for the character each contained in the same spritesheet.
The character sprite sheet is roughly 4000x3500
The character is roughly 350x250 px
Other objects also use the same sprite sheet. Currently there is only one object.
Possibly helpful questions:
Am I using too many spritesheets or too few?
Should I only draw something if it's coordinates are in bounds of the screen?
How should I go about garbage collection? Do I need to set image objects to null when no longer in use?
Thanks in advance for input. I would just like to know if I am going about it the right way and pick your brains as how to speed it up enough.
*Note that I plan to port the JS game to cocoonJS which provides graphics acceleration for the canvas element on mobile.
** If interested please visit my Patreon page for fun!
You have asked lots of questions here, I'll address the ones I've run into.
I would like to start out by saying very clearly,
Use a profiler
Find out whether each thing you are advised to do, by anybody, is making an improvement. Unless we work on your code, we can only give you theories on how to optimise it.
How should I go about garbage collection? Do I need to set image objects to null when no longer in use?
If you are no longer using an object, setting its reference to null will probably mean it gets garbage collected. Having nulls around is not necessarily good but this is not within the scope of this question.
For high performance applications, you want to avoid too much allocation and therefore too much garbage collection activity. See what your profiler says - the chrome profiler can tell you how much CPU time the garbage collector is taking up. You might be OK at the moment.
I then use the drawImage function to cycle through and draw each tile on a part of the canvas using information (w, h, x, y) stored in the tile array. I do this on every cycle of the main loop using my drawMap function.
This is quite slow - instead consider drawing the current on screen tiles to a background canvas, and then only drawing areas which were previously obscured.
For example, if your player walks to the left, there is going to be a lot of tiles on the left hand side of the screen which have come into view; you will need to draw the background buffer onto the screen, offset to account for the movement, and then draw the missing tiles.
My game is tile based - using tiles designed at 500x500 px because I want them to display decently on high definition devices
If I interpret this right, your tiles are 500x500px in diameter, and you are drawing a small number of these on screen. and then for devices without such a high resolution, the canvas renderer is going to be scaling these down. You really want to be drawing pixels 1:1 on each device.
Would you be able, instead, to have a larger number of smaller tiles on screen - thereby avoiding the extra drawing at the edges? Its likely that the tiles around the edges will sometimes draw only a few pixels of one edge, and the rest of the image will be cropped anyway, so why not break them up further?
Should I only draw something if it's coordinates are in bounds of the screen?
Yes, this is a very common and good optimisation to take. You'll find it makes a big difference.
Am I using too many spritesheets or too few?
I have found that when I have a small number of sprite sheets, the big performance hit is when I frequently switch between them. If during one draw phase, you draw all your characters from character_sheet.png and then draw all the plants from plant_sheet.png you'll be ok. Switching between them can cause lots of trouble and you'll see a slow down. You will know this is happening if your profiler tells you that drawImage is taking a big proportion of your frame.

How can I increase map rendering performance in HTML Canvas?

We are developing a web-based game. The map has a fixed size and is procedually generated.
At the moment, all these polygons are stored in one array and checked whether they should be drawn or not. This requires a lot of performance. Which is the best rendering / buffering solution for big maps?
What I've tried:
Quadtrees. Problem: Performance still not as great because there are so many polygons.
Drawing sections of the map to offscreen-canvases. A test run: http://norizon.ch/repo/buffered-map-rendering/ Problem: The browser crashes when trying to buffer that much data and such big images (maybe 2000x2000) still seem to perform badly on a canvas.
(posting comments as an answer for convenience)
One idea could be, when the user is translating the map, to re-use the part that will still be in view, and to draw only the stripe(s) that are no longer corrects.
I believe (do you confirm ?) that the most costly operation is the drawing, not to find which polygon to draw.
If so, you should use your QuadTree to find the polygons that are within the strips. Notice that, given Javascript's overhead, a simple 2D bucket that contains the polygons that are within a given (x,y) tile might be faster to use (if the cost of the quadtree is too high).
Now i have a doubt about the precise way you should do that, i'm afraid you'll have to experiment / benchmark, and maybe choose a prefered browser.
Problems :
• Copying a canvas on itself can be very slow depending on devices/Browsers. (might require to do 2 copy, in fact)
• Using an offscreen canvas can be very slow depending on devices/Browsers. (might not use hardware acceleration when off-screen).
If you are drawing things on top of the map, you can either use a secondary canvas on top of the map canvas, or you'll be forced to use an off-screen canvas that you'll copy on each frame.
I have tried a lot of things and this solution turned out to be the best for us.
Because our map has a fixed size, it is calculated server-side.
One big image atlas with all the required tiles will be loaded at the beginning of the game. For each image on the atlas, a seperate canvas is created. The client loads the whole map data into one two-dimensional array. The values determine, which tile has to be loaded. Maybe it would be even better if the map was drawn on a seperate canvas, so that only the stripes have to be painted. But the performance is really good, so we won't change that.
Three conclusions:
Images are fast. GetImageData is not!
JavaScript has not yet great support for multi threading, so we don't calculate the map client-side in game-time.
Quadtrees are fast. Arrays are faster.

Canvas vs DOM Element game and collision

So I am trying to make a little game both for practice and fun (first time I have tried) never had anything to do with it before..
You can see what I've tried so far at: http://myfirstgame.e-ddl.com/ been working on it for like 6-8 hours or so. So far and realized I would better ask before going on.
The way I have it now, I have a main loop that runs every 20 milliseconds or so. Ihis loop calls 2 functions:
Handle keystrokes (which iterates through the obstacles array and check if the player's future position collide any obstacle object and change the players' properties to the future position values).
It goes through the "need update" array and change the element's CSS details to reflect the changes made.
I have several questions:
Is the above a good idea to handle collision? if not what would be a better way (I mean at around 800-1500 obstacle objects on map the game slows down).
To calculate distance, I use distance between 2 points equation. If I only have 1 point, angle and distance. How can I find the 2nd point's (x, y)?
What would be better, canvas or DOM ? (not important question as I already have it done with DOM).
Thanks for everyone.
I've found the solution to what i were looking for.
about the collision the way i was doing it was entirely wrong i will list the correct way farther down.
about the distance - the solution i came up with is checking the distance from player's current position to object if player's step is bigger then distance, deduct step from distance and walk that distance.
as for canvas vs dom - seems both has their crons and pros.
Now for the collision
the correct way of doing it is to create a pixel map array. so if your canvas or container node is width:800 by height:500 you'll have a 2d array that represent those pixes
and then when i check for position i simply check if player's current position + steps toward future position has an object.
so like :
if(array[300][500]){
return false;
}
That's what i found out.
If anyone have a better solution then that let me know.

Get Second Point By First And Distance

I'm building an online game, and using node and whatnot, anyway i'm not too keen on constant streams and streams of data just for animations, i've set up a way for it to animate client side and so on... but i found a problem, all i was doing was setting the new coordinates and telling all the clients to animate their character to that point, but if you refreshed the page, the player would be there instantly.
I have got a distance,speed of movement,time of movement,start and destination... i know where they started moving, i know where their destination is, i know when they started moving and at what speed, and in a linear fashion.
What i need to work out, is where the player is (whilst animating) at that specific time when other players join the game.
Try http://en.wikipedia.org/wiki/Kinematics
Or http://en.wikipedia.org/wiki/Speed
the distance travelled can be calculated by rearranging the definition to d=v*t
The simplest approach would be to tween the position. That involves creating a series of intermediate steps along the path between the current position and the updated one. This works best if you know the frequency of updates. You can choose these points linearly or use an easing function to smooth it out.
If you really are doing a physical simulation though, it'll probably look more natural if you take the physical model into consideration. I'd try the simple case first before seeing whether you need to go into more mathematically complex territory.

Merging pixels to minimize paint operations on Html canvas

Hi I'm painting an image onto a canvas (html5) and I want to reduce the number of fillRect calls I'm making in the hope of making the process more efficient.
Note: I'm calling canvas.fillRect to paint individual pixels and pixels can be 1x1 or other size rectangle depending on resolution I'm painting in (So I know that they are not called pixels but my image vocab is limited).
What I would like to do is find and merge individual pixels if they are the same colour. This will reduce the number of calls to fillRect and hopefully be faster than what I currently have.
So lets say I have a bit map like this:
[fff, fff, fff]
[f00, f00, f00]
[00f, 00f, 00f]
Instead of making 9 calls to fillRect I would like to make 3.
So my questions are:
1) What is this process called (so I can do some more intelligent research, as googling 'merging pixels', 'merging rectangles', etc, yields no useful results).
2) Anyone aware of any open source library that implements this (does not have to be javascript)
3) Does anyone think that adding this pre-processing step will actually make the code slower in JS?
Thanks All
Guido Tapia
I would agree with #Jakub that doing this kind of analysis in Javascript is likely to take a lot longer than the time you save by filling fewer rectangles (usually a very fast operation for a graphics card). That is unless you have to paint the same set of rectangles many thousands of times.
As for what it's called, the closest thing I can come up with is run-length encoding, which admittedly is one-dimensional rather than two.

Categories

Resources