Iterating through lots of objects - java

I have an ArrayList with 40,000 separate objects that can be drawn to the screen. Right now I have to iterate through all of them, and perform a calculation if they are showing on the screen, before I draw them with a Graphics2D object.
for (GameObject object : gameObjects) {
if (insideScreenView(object)) {
object.draw(g2d);
}
}
This doesn't take too long, but it does take about 2-5 ms. Only about 100 of these objects are showing on the screen at any given time. Meaning that I am running 39,900 iterations that aren't necessary. Is there a better way to do this, given that I know most iterations don't have to happen.
Edit:
Objects are chosen to be on screen based on if an object's bounding rectangle intersects the screen via Rectangle's intersects() method.

Instead of iterating ALL the game objects, you should iterate only the viewable objects.
So, how to do that?
->> METHOD 1 (slow, but simple) <<-
First, separate your game logic in 2 pieces: updateView(), and draw().
updateView():
Here, you calculate what objects are inside the screen, and add them to a simple List (you can choose ArrayList or LinkedList, each one will have different performance impact, so, benchmark them!).
draw():
Here, you iterate over all the objects on the List you created before on updateView, and draw them.
->> METHOD 2 (fast, but complex) <<-
The basic logic is somewhat like Method 1: you have the viewable objects inside a List, and draw them on draw() method. But the difference between these methods is that, on this method, instead of each tick verify what objects are viewable, you check when the objects move.
Depending on how your Game Objects are managed, Method 1 can be faster (if your Game Objects are moving every time, like particles), but for general purposes, this method is faster.
So, inside Game Object, you add a boolean called addedToViewList. This boolean indicates whether the object is added to the viewable objects list, so we don't need to use list.contains(object) and iterate over it. Then, every tick, you check if the object is already on the list. If it is, you check if he is viewable or not: if not, you remove him from list. If he wasn't on the list, but he is viewable, then you add him to list.
Example:
public void onMove() {
if (addedToViewList && !insideScreenView()) {
this.addedToViewList = false;
(view list).remove(this);
}
else if (!addedToViewList && insideScreenView()) {
this.addedToViewList = true;
(view list).add(this);
}
}
Hope I helped you. See ya!

Related

Disable repainting after modifying graph in Jung

I've a graph in Jung shown using a JFrame.
After I remove a vertex from the graph,
the shown graph automatically redrawn and presented without the removed vertex.
How can I disable it, so that only when I call the repaint method
the graph would be redrawn ?
Thank you
The simple way to do this is extend your graph by some class and add toRemove() method, where you can signify your vertex to delete in boolean array. And the second method deleteNow() which will use your boolean array and delete your vertexes - it will be alike repaint() now. The second way is add boolean value to your vertex instead of array in your extended class. I can't find any other way. Sorry if it's not helpful.
You haven't really given enough information to be able to advise you precisely, but here are some general observations.
The answer to your question is going to depend in part on how you're removing the vertex: interactively or programmatically.
If it's programmatically, then you'll need to look at the code that calls VisualizationViewer.repaint(). It's been a while since I've looked at that part of the code, but the gist is that something is listening to changes to the graph model and triggering repaints (because this is what users generally want).
If it's interactively, then it's probably on the same thread as your visualization, and you should have a fair amount of control over when repaint() gets called (see the calls in the sample code to VV.repaint()).

How to make multiple references to same object in Java

I am implementing a crossword puzzle backend.
Crossword is composed of slots is composed of cells.
Lets say cell at (3,14) has a value of "a"
I want crossword.changeCellValueByCoordinate(3,14,"x") to do "a"->"x"
Lets say some Slot slot has a head cell at coordinate (3,14)
Slots head can be identified by (2,across) == Cell(3,14)
So when I call slot.getCellValueByNumberAndDirection(2,across) next, it already changed from "a" to "x".
And another method (for the same cell) crossword.getSlot(2,across).getHead also changed from "a" to "x".
How do I make it so all three objects of different types (Crossword, Slot, Cell) has an attribute (perhaps of same name, lets call it "content") that is shared/referenced by all Classes?
There are lots of ways to handle this. Here's one way:
I don't care too much for the "Slot" class. This does nothing to help with the intersections between the clues.
When you look at a crossword puzzle, what do you see? I see a board of empty squares. Some have little numbers in the corners. I also see dark blocks I know I can't write in. I see a list of "down" clues, and a list of "across" clues.
No matter what I do, I write on that board of empty squares. So I'd make a grid-like class called Board that would allow me to write on it. The little number in some squares would be how specific words are indexed. The contents of each cell could be a space, a letter, or a -1 if the square isn't writable.
You might choose to implement a Square (or Cell) class. It would include a flag stating the instance's ability to be written to. It could include a number signifying the cell to which a clue applies. There are more elegant ways to do this. Implement this, and we can discuss more advanced class hierarchies.
The Board class would contain an NxN structure (probably an array) of Cell instances.
Another class would be called something like "Clues" that corresponds to the down or across list of clues. Clues includes a list of Clue instances.
Finally I'd have a Clue class where each instance includes an ID (the 15 in "15 down" for example), and the clue text to be displayed.
I think once you initialize the Board, you'll have all you need to make a nice crossword program.

ParkingSimulation infinite while loop crisis

I'm a beginning computer science student and we've been asked to complete a project that animates random generated car objects moving to randomly generated parking spots on a city map grid. I've developed a GUI for the buttons, text fields, and text areas. Everything works as required except for at the end of the animation, when all cars have reached parking spots, I need to display analytics in my JTextArea. My buttons are set up properly and I will show you where the code takes place below:
else if (e.getSource() == start) {
setAnimate(true);
if(simulator.simulationFinished()) {
createAnalytics();
}
}
So here I have implemented an action listener on the button "start" that begins the animation. Currently it:
currently it begins the animation and all the cars travel to the parking spots as intended.
it displays analytics that are derived from before the animation began (Analytics include: car ID, number of moves, average number of spots tried, average distance travelled)
then the animation will conclude.
If I press the start button again it will display the proper analytics.
I know that in order for the program to display the right analytics the moment the program finishes I most likely need a while loop, however I haven't been able to dream anything up that will not create an infinite loop and require me to manually terminate the program via console.
while(!simulator.simulationFinished()) {
if(simulator.simulationFinished() == true)break; {
createAnalytics();
}
}
I've also tried this among several hundred other variations of all the loops in existence. Following from my logic, I need the while loop so that it will keep checking to see if the simulation is finished so that I can execute my method that generates analytics, but if don't give the while loop something to do it just goes on forever and crashes. I'm at a loss, any help would be appreciated. Thanks.
First: no, you don't need a while loop necessarily. You could use the observer pattern instead (for example) and your object would be notified as soon as the simulation had finished. As to your question: the if inside the while is obviously superfluous (as is the == true). The real problem seems to be that simulator.simulationFinished() never returns true. Could you post the code of that function and the code (and any code that directly influences the return value of it)?
Without going into details, there's a serious problem with your while loop.
See, it loops as long as simulator.simulationFinished() returns false.
However, within the loop, you check for the opposite - which will never happen.
I would recommend using listeners of some sort, although the requirement is not clear enough for me to advise any further.

AndEngine - Sprites remaining on screen...sometimes

I'm attempting to create an Android game using AndEngine and have been having some successes. I'm trying to make a Target Tap clone which basically involves tapping a number of different targets on the screen to remove them (a bit like whack-a-mole).
It works perfectly with one target and I can quite easily tap on it to remove it. The problem is that when there is more than one target on the screen they don't always disappear but adding points and everything else that is supposed to happen when you hit one works.
I am removing the sprites in (as far as I know) the correct way which is to do it inside the runOnUpdateThread(...) block.
Game.runOnUpdateThread(new Runnable() {
#Override
public void run() {
// Loop through all targets and check validity
for (Iterator<Target> i = Game.this.mTargets.iterator(); i.hasNext();) {
Target t = i.next(); // Target extends Sprite
// If the target isn't valid, remove it from the scene and ArrayList
if (!t.isValid()) {
scene.unregisterTouchArea(t);
scene.detachChild(t);
Game.this.mTarget.remove(t);
}
}
}
Sorry this is a little brief but because I'm unsure about where the problem lies I don't know what code to supply. I'm currently unable to test it on a real device but was wondering if this is could simply be something to do with the emulator because as far as I can tell the code is correct and I've tried so many things. If you need any help helping me, just let me know!
Thanks
It looks like you're skipping in the ArrayList when you remove one. Say you're on targets(5) and it comes up invalid. It then removes the 5th element from the list and shifts everything from there on down one, so the old 6th is now 5th. Then when you loop back through, you hit next() right past the new 5th element.
Normally what I do in this case is either:
(a) Run through the list backwards, or
(b) set a boolean to true if I remove one, and check it before performing the next() function in the next iteration. Or, more likely..
(c) don't use iterators, and instead use the get() function, ie
for (int i=0;i<Game.this.mTarget.size();i++) {
Target t = Game.this.mTarget.get(i); // Target extends Sprite
// If the target isn't valid, remove it from the scene and ArrayList
if (!t.isValid()) {
scene.unregisterTouchArea(t);
scene.detachChild(t);
Game.this.mTarget.remove(t);
// Decrease i to keep in sync with the new list
i--;
}
}

The Elegant way to handle Cyclic Event in Java?

i think this not a specific problem to me; everybody might have encountered this issue before.
To properly illustrate it, here's a simple UI:
As you can see, those two spinners are controlling a single variable -- "A". The only difference is that they control it using different views.
Since these two spinners' displaying values are synchronized, cyclic event shows up.
If i change the top spinner, "A" will be changed and the bottom spinner's value will also be updated accordingly. However, updating the bottom spinner's call (such as setValue) will also trigger another event instructing the top spinner to update based on the bottom spinner's value. Thus creates a bad cycle which can eventually cause a StackOverFlow exception.
My previously solution is kinda cumbersome: i placed a guarding boolean to indicate whether the 2nd updating call should be performed.
Now i'd like to ask "how can i handle such situation elegantly? ( in general, not specific to spinners )"
thx
Update:
Since i've got 2 answers suggesting me to utilize the observer structure, i have to say something about it.
Like what i've said, it's great but far from being perfect. Not only because of its inherent complexity, but also Its inability to solve the problem.
Why? To see the reason, you must realize the tight coupling of the View and Model-Controller in Java Swing. Lets take my spinner UI for an example. Suppose the variable A is actually an Observer object. Then, after firing the first state change event from the top spinner, the Observer "A" will update its value and fire a PropertyChange event to notify the bottom spinner. Then comes the 2nd updating which updates the bottom spinner's View. However, changing bottom spinner's view inevitably triggers a redundant event that will try to set "A"'s value again. Afterwards, the deadly loop is fully constructed and the stack overflow will be thrown.
In theory, the Observer model tries to solve the direct cycle by introducing 2 independent feedback paths. The chained updating odds(in event-response codes) implicitly form a bridge connecting both paths, making a cycle again.
Going back to Model-View-Controller, think about what your Model is, and what your View is.
In your current implementation, you have two models (one for each Spinner control), and they're being synced through the View layer.
What you should be doing though is share the same backing model. For the spinner with a subtracted value, create a proxy to the original model. ie:
class ProxySpinnerModel implements SpinnerModel {
getValue() { return originalSpinner.getValue() - 10 }
setValue(v) { originalSpinner.setValue(v+10) }
}
spinnerA = new JSpinner()
spinnerB = new JSpinner( new ProxySpinnerModel( spinnerA.getModel() ) )
Now, you don't need to add listeners, since they're both working off the same model and the default implementation (the originalModel) already has change listeners which it fires to the view.
Problem Solved
I've got many different suggestions. Particularly,
i want to thank Marc W & Reverend Gonzo. I'm here to make a summary for these ideas; this can save your time navigating thru big chunk of texts.
This problem can be easily bypassed if you carefully decouple the View and Model-Controller.
The dead cycle is caused by dependent writes: write_1 -> write_2 -> write_1 ->.... Intuitively, breaking the dependency can solve the problem elegantly.
If we look into the problem in depth, we can find updating the corresponding views doesn't necessarily involves an external write call. Actually, a view only depends on the data it's representing. Known this, we can then re-write the logic as follow: write_1 -> read_2 & write_2 -> read_1.
To illustrate this idea, lets compare the 3 methods mentioned by different posters:
alt text http://www.freeimagehosting.net/uploads/2707f1b483.png
As you can see, only the proxied view can solve all the dependency thus it's the generic solution for this knid of problem.
In practice, it can be implemented as something like this (in your event-response codes):
setValue(newValue);
anotherSyncUI.parse(); // not anotherSyncUI.setValue() any more
anotherSyncUI.repaint();
No more loops. Solved.
It's a bit complicated, but you could make A actually be an object that's observable. Both spinners (or whatever needs to update itself based on A's value) would then observe A. Whenever A changes, the spinners (or again, whatever object) update themselves to reflect the new value of A. This decouples the spinners' logic from one another. In your example here, the spinners should not be coupled to one another because they really have nothing to do with each other. Instead, they should both simply be bound to A and take care of their own view updating individually.
Whenever the value in the first spinner is changed, you would simply update A's value to match it. Whenever the value in the second spinner is changed, you would of course add 10 to its value before assigning it to A.
Update
In response to the update to your original question, my answer is that the spinners do not listen to one another's change events. Have a separate event handling method for each spinner. A user clicking the up or down arrows in the spinner generates a different event than calling setValue on the spinner programmatically, correct? If the spinners are completely independent of one another, there will be no infinite loop.
E.g. for the second spinner, calculate A-10 and then compare it to the current value of the spinner. If it's the same, do nothing, ending the infinite loop. Similarly for the first spinner.
I think there are also ways to update the spinner's model in a way that doesn't fire an event, but I don't know them off the top of my head.
Use a single SpinnerModel for both JSpinners. See the following code:
Note that the call to setValue() is only made once each time a new value is defined by one of the JSpinners.
import java.awt.BorderLayout;
import javax.swing.*;
public class Test {
public static void main(String[] args) {
JFrame jf = new JFrame();
SpinnerModel spinModel = new MySpinnerModel();
JSpinner jspin1 = new JSpinner(spinModel);
JSpinner jspin2 = new JSpinner(spinModel);
jf.setLayout(new BorderLayout());
jf.add(jspin1, BorderLayout.NORTH);
jf.add(jspin2, BorderLayout.SOUTH);
jf.pack();
jf.setVisible(true);
jf.setDefaultCloseOperation(3);
}
}
class MySpinnerModel extends AbstractSpinnerModel {
private int _value = 0;
private int _min = 0;
private int _max = 10;
#Override
public Object getNextValue() {
if (_value == _max) {
return null;
}
return _value + 1;
}
#Override
public Object getPreviousValue() {
if (_value == _min) {
return null;
}
return _value - 1;
}
#Override
public Object getValue() {
return _value;
}
#Override
public void setValue(Object value) {
System.out.println("setValue(" + value + ")");
if (value instanceof Integer) {
_value = (Integer) value;
fireStateChanged();
}
}
}
It seems you're really observing the wrong thing. From the example given I presume what you want to detect is the user's actions on the controls, not the changes in the values themselves. As you've outlined, changes in your model are reflected in the values of the spinners, and it is this which forms the infinite loop of events.
However, diving further into the UI implementation may not be the answer you want. In that case I'd say the best you can do is either your current guard solution, or to better extract the logic into your model (similar to what Marc and William have said). How that can be done will depend on the 'real world' model behind a particular implementation of the provided puzzle.
As a rule, your model should not be defined by your GUI. Ie, the SpinnerModel that backs each JSpinner should not be your value A. (That would be a horribly inelegant tightly coupled dependency on a particular view.)
Instead, your value A should either be a POJO or a property of an object. In which case, you can add PropertyChangeSupport to it. (And presumably have already done so in any case, as you want your spinners to update automatically if A is changed by other parts of your program).
I realise this is similar to Marc W's answer, and you were concerned that it's "complicated", but PropertyChangeSupport does almost all of it for you.
In fact, for trivially simple cases, you can just use a single class that wires a "setProperty" method through to a "firePropertyChange" call (as well as storing the value in a HashMap for any "getProperty" calls).
I don't really want to solve your problem but I find it interesting. I have already been confront to it and solved it each time a different way. But when I think about the 'why ?' and not about the 'how ?' am staying perplexed.
This problem only exists because I am using an automatism (MVC) which had to help me, and exactly in that way. The art how the components are used make this automatism a barrier to a beautiful code.
Why do set #setEvent() has to produce the same event as a GUI action?
Though, my opinion is also pretty close to Observer pattern but it is a bit lighter than that!!!
Have A as a variable with a setter
private Integer A;
setA(int A)
{
this.A = A;
refreshSpinners();
}
refreshSpinners()
{
setSpinnerA();
setSpinnerAMinus10();
}
setSpinnerA()
{
// show value of A
}
setSpinnerAMinus10()
{
// show value of A-10
}

Categories

Resources