Reputation: 117
I'm programming a big game in Java and I'm trying to optimize the code but also to keep the code neat and well organized. Now I am unsure if I should use the public static field of single classes that have a couple of variables that are used by a lot of instances.
For example the class camera has an x and y position that define what part of the map the user is looking at and what needs to be drawn to the screen. Currently I'm benchmarking with 50 000 units and I have the following options to draw them.
1: Store a reference to the instance of the camera in each unit and call getX() and getY() when it should be drawn:
public void paint()
{
paint(x - camera.getX(), y - camera.getY());
}
2: Supply the coordinates of the camera as arguments to each unit when it should be drawn:
public void paint(int cameraX, int cameraY)
{
paint(x - cameraX, y - cameraY);
}
3: Make the x and y variables of the camera class static:
public void paint()
{
paint(x - Camera.x, y - Camera.y);
}
I'm interested as what is generally seen as the best solution and if it affects performance. Perhaps there are more ways to do this I haven't thought of yet?
Thanks!
Upvotes: 5
Views: 443
Reputation: 123
I had the same question for the same reason (a big java game).
I've tested two ways for a variable that represent the time since the last frame, it's use in every instance of every object at every frame.
One way is a static, the other way is the pass that variable as an argument down from the main loop to every subclass of every object.
Here are my results : https://i.sstatic.net/WtSue.png
I've tested each way 3 times. As you can see the result are pretty similar except between 130s and 210s, I can't really explain why.
Upvotes: 0
Reputation: 11
Enumerate and calculate to millisecond to m.server by using integer vaule.
that is guest without looking at any books.
Upvotes: 1
Reputation: 45079
I'd suggest you create a Painter class and do the following:
public void paint(Painter painter)
{
painter.draw(x, y, unit_sprite);
}
That way the units don't have to worry about the existence of a camera. It is none of the unit's business how that works. The unit just needs to know how to draw itself on the global co-ordinate scheme and the painter will understand how that relates to the actual screen co-ordinates.
Why is this a good idea?
Regarding your proposed solutions:
Regarding performance:
The difference is going to be almost nothing. I'm not sure what method will win in a performance battle, but I can tell you if you have performance issues they are going to be somewhere else (I'd guess in actually blitting functions). By combining all the code relating the offsets is a single location, my proposed method will make it easier to implement an optimization. For example, a common optimization is not draw things which are offscreen. If you have 20 functions all calculating offsets and invoking drawing functions, you'll have to go to each of those function and change them. If you use a painter, then you can simply change the painter class to ignore request to draw outside of the visible area and you are done.
Regarding static variables in general:
I consider static variables (and singletons) to be global variables and thus virtually never use them. Making them static ties me to particular decisions. I'm not smart enough to make all the right decisions up-front and so I need my code to be flexible.
Some Guidelines:
Upvotes: 3
Reputation: 10454
Just time it and see.
long startTime = System.currentTimeMillis();
for(int i=0; i<1000000; i++){
// Call your code
}
System.out.println("Total time " + (System.currentTimeMillis() - startTime) + " ms");
My guess is the JIT will take care of the differences and they will all be roughly equivalent. There's no substitute for timing it yourself. Additionally, I would recommend profiling the app and see where the time is spent when running your app before doing these kinds of micro performance tweaks.
Upvotes: 0
Reputation: 106401
You'll have to benchmark in your context to be sure but here is my experience:
Upvotes: 1
Reputation: 43331
In all programming languages, it is always recommended to use get/set methods for both static and instance members. This allows to change internal implementations transparently for a client code, if this is necessary. However, sometimes these rules are broken, if performance is very important.
Upvotes: 0
Reputation: 46394
Overall the second should provide a good balance; it also will ensure that you don't accidently hold references to the camera beyond when you anticipate, or that you don't run into conflicts with stateful static fields.
Keep in mind that you should still profile the performance regardless of whatever solution you choose--but don't anticipate this being a bottleneck until you have evidence that it is one.
Upvotes: 0
Reputation: 6317
If you have only one camera at all times, i would choose the third way. Otherwise i would choose the second way.
I think that from performance point of view, using a public static field is a good idea. As far as code readability goes, if it is easily understood that there is only one camera at all times, this should be ok too.
Upvotes: 2