Hey, (Very long email, if you don't have time to read it, go to "PROPOSITION" at the end)
I would like to improve Wormux speed, because like a friend said to me: "Worms 1 ran on a 486 [ and Wormux need 2 GHz ]" !!! For sure, Wormux need too much CPU and memory. So I wrote a tool to benchmark Wormux: view_stat.py, written in Python. You have to add StatStart() and StatStop() functions in the code, run Wormux, and then read result using this tools. Example: StatStart("Draw:sky"); sky.Draw(); StatStop("Draw:sky"); ... StatStart("Draw:map"); map.Draw(); StatStop("Draw:map"); ... It would be possible to disable stats (so, it doesn't impact of performance), I prepared #define, but doesn't work with ./configure yet. So, most important result: in game loop, Draw() eat 99% of CPU and Refresh() 1% !!! WTF !? It means that *all* CPU is used only to display. I tried to improve Draw() function. Most interesting point: only draw sky+ground once (or when the camera moved) make Wormux really faster. - On my computer : 21 fps => with the patch (*) : 75 fps !!! - On a friend computer : 40 => 120 fps !!! So I "think" that we have to work around ... no ? :) My patch can't be applied because when the sky+ground isn't refreshed, objects aren't removed when they move ... (*) "The patch" => in map/ground.cpp and map/sky.cpp, replace "#if 0" with "#if 1" (in Draw() functions). --- PROPOSITION --- Idea: I propose to write a cache for the whole screen. We just need one big cache which would know "what have to be draw". The game would not ever ask object to draw them, but ask the cache to draw objects which "have moved" (or if another object is removed/moved at same position). The cache would be a list of rectangles where the screen has to be redrawn. Start of game and when the camera move: cache.Invalidate(<whole screen>) When an object move: cache.Invalidate(<old rectangle>) cache.Invalidate(<new rectangle>) When an object is removed: cache.Invalidate(<old rectangle>) (...) The cache have to manage a list of rectangle and do intersection of two rectangles. Example: +---+ +---+ | A | | B | +---+ +---+ => can be stored as (A, B) or +----------+ | big A+B | +----------+ We have to test if it's faster to draw A and then draw B (which means call Draw() function of each object twice), or just draw a bigger rectangle. Draw function of a sprite/object would become: void Object::Draw(Rectangle draw) { Rectangle intersection = Intersection(this.rect, draw); if (intersection.isEmpty()) return; Blit(surface, intersection, ...); } What do you think about the cache? I think that I would be "easy" to write the cache, but very difficult to "upgrade" all Draw() functions ... Bye, Haypo -- Victor Stinner - étudiant à l'UTBM (Belfort, France) http://www.haypocalc.com/wiki/Accueil
signature.asc
Description: This is a digitally signed message part