All basic Pygame examples I've seen just redraw the background over everything and then the sprites over that. This should cause performance issues later on (because you're adding at least 2 new images to the window for every frame rate tick without ever removing them).
Is there a better way?
If updating the entire screen is fast enough, this is already the "best" way, since it's the simplest.
If drawing to the screen is a performance bottleneck, then it can be better to just update only the parts of the screen that are changed. You probably want to use pygame's DirtySprite and LayeredDirty classes. LayeredDirty's draw function returns a list of Rect instances that describe the parts of the screen that needs updating, and you can just pass this list to pygame.display.update.
Related
I've seen people using multiple canvas instead of a single one. Why? Is there better performance? I haven't seen much of a difference.
Multiple canvas are usually used when:
their framerate is different from each other. As an example, consider a canvas where a game main screen is displayed and another canvas where the inventory is displayed. The game should be constantly updated, but the inventory may be static (or less frequently updated).
it would be harder to correctly position all the elements in just one canvas. In these cases, the combination multiple canvas + CSS is generally used to make positioning substantially easier.
a more flexible layout is required. As an example, consider that previous scenario that I made (a game screen and the inventory). Supposing that the player wants to hide his inventory, it would be much easier to accomplish this by using multiple canvas (you can just hide the canvas where the inventory is at (using javascript)). If only one canvas would be used in this case, it could potentially require a much bigger code and cause you a lot of bugs and frustration.
I have many small, identical vector circles that move around the screen, but only appear for a defined period in defined areas. Currently, these circles are children of whatever parent object produces them, and each is given its own interframe handler for animation (move a few pixels, maybe change alpha). With hundreds on screen, this gets somewhat slow.
Would it be advisable to cache the circles as bitmaps? Would it be better to add them all to one array and have one interframe event handler run through the whole shebang, even if up to 90% aren't being animated in a specific frame?
Would it be faster to cache one circle as a bitmap and set all others to use the first shape's bitmapdata? Would it be even better to use a "CopyPixel" approach to erase and redraw ("blit") every circle at its new position every frame? I hear conflicting reports of the usefulness of CopyPixel on large mobile device canvases...
If the animation can be looped make a movie from the movie else try everything you can. Usually a CopyPixel approach is faster but I wouldn't expect much. I don't think it pays the bill either hence reduce the numbers of circles.
I hope this isn't too open ended.
I'm wondering if there is a better (more battery-friendly) way of doing this --
I have a small HTML 5 game, drawn in a canvas (let's say 500x500). I have some objects whose positions I update every 50ms or so. My current implementation re-draws the entire canvas every 50ms. I can't imagine that being very good for battery life on mobile platforms.
Is there a better way to do this? This must be a common pattern with games.
EDIT:
as requested, here are some more updates:
Right now, the objects are geometric primitives drawn via arcs and lines. I'm not opposed to making these small png/jpg/gif files instead of that'd help out. These are small graphics -- just 15x15 or so.
As the game progresses, more and more of the screen changes at a time. However, at the start, the screen changes relatively slowly (the objects randomly moved a few pixels every 50ms).
Nearly every game with continuous animation like this redraws everything every frame; clever updating algorithms are only applicable when a small part of the screen is changing and there is a nice rule to figure out what is overlapping that part.
Here is some general optimization advice:
Make sure that as much as possible of your graphics are handled by the GPU and not the CPU. (This may be impossible if the user's browser does not use the GPU for 2D canvas rendering, but you can expect upgrades may change that as HTML5 gaming gains popularity.)
This means that you should avoid elaborate clever algorithms in favor of doing as little work as possible in JS code — except that avoiding performing a lot of drawing when it is easy to determine that it will be invisible (e.g. outside the bounds of the screen) is generally worthwhile.
If your target platforms support it (generally not the case for current mobile devices), try using WebGL instead of 2D Canvas. You will have to do more detail work, but WebGL allows you to use operations which are much more likely to be provided efficiently by the GPU hardware.
If your game becomes idle — that is, nothing is actually animating at the moment — stop redrawing. Stop your update loop until the user interacts with the game or a timeout occurs.
It may be helpful for you to add to your question details of what types of graphics you are drawing (e.g. are you using sprites, or geometric primitives? Are you drawing images rotated/scaled? Does most of the screen change or just a few small objects? Are you blending many layers?) and perhaps even a screenshot or two; then we can suggest what sort of optimizations are suitable for your particular game.
Don't draw a background, make it an image and set the CSS background-image of the canvas.
Using requestAnimationFrame should help with battery life.
http://paulirish.com/2011/requestanimationframe-for-smart-animating/
Only do a redraw if something has actually changed. If you haven't already, introduce the concept of invalidations. (ie, the canvas is valid so nothing redraws until something moves. Anything moving within the window of the canvas causes the canvas to become invalid, thus needing a redraw)
If you want to be battery friendly you can use Crafty. This game engine is using modern CSS3 technology so it doesn't need to update a canvas all the time. Look at this example game here.
The way you don't want to redraw entire canvas every frame, it only can be the "Dirty-Check" or "Dirty Matrix" algorithms.
Dirty-check seems more efficient than entire redraw. but I think it depends on your render implementation.
it is not necessary to use it if you are using canvas2D to render. Nearly every game has complex sprites and animation. if you use dirty-check, when a part of sprite or background map need to update, you have to figure out what is overlapping this part. and then clearRect this small area of canvas, and then redraw every sprite or map. etc, what is overlapping.
It means your had to run canvas render api more times than normal render implementation because of the overlapping part. And Canvas2d render performance usually does't sounds efficient.
But if you use WebGL, that maybe quite difference. even though I am not family with WebGL, I do knew that maybe more efficient. Dirty-Check should be a good Choice to match your propose.
I am starting to get a grasp of the HTML canvas and I wanted to know if it is encouraged to use optimization techniques. In games for example, is it encouraged to use bounding boxes and only redraw the portion of the screen that needs redrawing, or do people just blindly redraw everything. I ask this b/c I am creating a new engine for canvas and imposing bounding boxes complicates things greatly (ie. the user no longer has the freedom to quickly draw things to the stage).
Absolutely, it's almost always better to draw only what has changed on the screen at any one time. Attempting to draw everything causes unnecessary rasterisation of the images being drawn into one output image, when it's not even going to change on the screen.
In a small game I made a year ago, I was drawing a 2D array of tiles on the screen and getting around 15 frames per second. When I changed it to draw only the tiles visible on the screen, it was an amazing improvement. It will improve in this circumstance too.
I hope my English is good enough.
The Problem:
I am developing some canvas game, using context2d. I did a perfomance test to see how well canvas render and stuff.
For painting, the method drawImage was used with some 50x50 jpg preloaded in memory at start.
My test was to instantiate a lot of logic square 50x50 objects moving random in the canvas
with no collission just to see the fps.
main loop was done with interval.
The problem, i noticed low fps when about 3000 random 50x50 on the screen, well i know the more you render, the less framerate. But i wanna ask something.
The question:
Is a good idea render every logic object in the canvas screen alone?
For example, with no collision, if i overlap two 50x50 in the same position, or almost the same position, the visible output is something lesser than (50·50)2 pixels, but i am drawing (50·50)2 pixels using drawimage for each element in the main loop.
Hope you guys understand the problem and the question.
Render alternatives? some logic techniques to archieve this instead of rendering every object alone?
I understand what you are asking, you are asking maybe you should try and rendering the collisions so you don't have to draw twice. Well frankly, I think you'd be better off just drawing the second square on top of the first one, and I'll tell you why:
Your logic will probably take more actions to determine the amount of overlapping and drawing the more complex shape, then actually drawing it.
So in my opinion, you'd be better off not testing for collisions in this one.
People, correct me if I'm wrong.
Definitely just draw. The bitblt (pixel copy) is optimized and will certainly be faster than collision logic between sprites. However, the one exception is possibly testing for off-screen sprites. This is a fast test because you're only checking against the screen bounds, that is, if a sprite is off the screen. If you have 10,000+ sprites, and many are off-screen most of the time - for example when zoomed in - then the test is worth it.. If they're always on screen, then just draw.