The best way to select spatials for removal?

Hi, I'm creating a simple puzzle game where you click on a sphere of  a color and it removes the same colored spheres next to it (think diamond mine) and I'm having some problems generating a list of spheres for removal the code I have at the moment just creates a continuous loop  :frowning:



            List<Vector3f> ballPicked = Collections.synchronizedList(new ArrayList<Vector3f>());
            ballPicked.clear();
           
            // Check if a ball was clicked
            if (pr.getNumber() != 0)
            {
                // Get the clicked ball's colour, geometry and position
               ballColor = pr.getPickData(0).getTargetMesh().getParentGeom().getRenderState(RenderState.RS_MATERIAL);
               ballGeom = pr.getPickData(0).getTargetMesh().getParentGeom();
               ballPicked.add(pr.getPickData(0).getTargetMesh().getParentGeom().getLocalTranslation());

               // Loop though the ballPicked array
               while (ballPicked.listIterator().hasNext() == true) {
                  // Set the iterator element to ballOrigin
                  Vector3f ballOrigin = ballPicked.listIterator().next();
                  if (ballPicked.listIterator().previous() != ballOrigin)
                  {
                     System.out.println(ballPicked.listIterator().hasNext());
                  // Cast ray from picked ball towards positive x
                  Ray ballRay1 = new Ray(ballOrigin, new Vector3f(1,0,0));
                  // Cast ray from picked ball towards positive y
                  Ray ballRay2 = new Ray(ballOrigin, new Vector3f(0,1,0));
                  // Cast ray from picked ball towards negative x
                  Ray ballRay3 = new Ray(ballOrigin, new Vector3f(-1,0,0));
                  // Cast ray from picked ball towards negative y
                  Ray ballRay4 = new Ray(ballOrigin, new Vector3f(0,-1,0));
                             
                  // Find the balls in all four directions
                  rootNode.findPick(ballRay1, bpr);
                  rootNode.findPick(ballRay2, bpr);
                  rootNode.findPick(ballRay3, bpr);
                  rootNode.findPick(ballRay4, bpr);
                               
                  for (int d = 0; d < bpr.getNumber(); d++)
                  {
                     float distance = bpr.getPickData(d).getDistance();
                     if (distance < 96 && distance > 33 && ballColor == bpr.getPickData(d).getTargetMesh().getParentGeom().getRenderState(RenderState.RS_MATERIAL))
                     {
                           rootNode.detachChild(ballGeom);
                           rootNode.detachChild(bpr.getPickData(d).getTargetMesh().getParentGeom());
                           ballPicked.add(bpr.getPickData(d).getTargetMesh().getParentGeom().getLocalTranslation());
                     }
                  }
                  bpr.clear();
               }
            }
        }
    }



Any ideas on how to fix this or should it be scrapped in favor of something better?

Thanks.

I did not stare quite long enough at the code to understand what you were doing there in the end and why it goes into a loop, but I just wanted to say that I would have implemented this by keeping my scene and game data more separate - Say maintain a multidimensional collection where the collection indexes represent the location of the sphere in the grid and the data is a reference to the Sphere itself. When a person clicks on the playing field I would find out where exactly he clicks and get the spatial not from the scene, but from the Collection. And also the neighboring Spheres could easily be taken by just playing with the Collection indexes.



Buuuut, it might not be the best solution for you :slight_smile: I guess it might have drawbacks depending on how you have done everything else.

How about array lists…


ArrayList<Sphere> red = new ArrayList();
ArrayList<Sphere> green = new ArrayList();
ArrayList<Sphere> orange = new ArrayList();
ArrayList<Sphere> yellow = new ArrayList();
ArrayList<Sphere> blue = new ArrayList();



Every time you create a new sphere, add it to the correct ArrayList.

Sphere s = new Sphere ("mySphere", 10, 10, 50);
red.add(s);
rootNode.attachChild(s);



Then when somebody clicks on a red sphere...


for(Sphere s : red)
    rootNode.detachChild(s);



Another way which would ditch the ArrayLists is to set the spheres of a specific color into a color-specific Node, then attach all of those nodes to the rootNode..

Node red = new Node("red");
Node blue = new Node("blue");
Node orange = new Node("orange")

rootNode.attachChild(red);
rootNode.attachChild(blue);
rootNode.attachChild(orange);



Then create your spheres and assign them...

Sphere s = new Sphere("redsphere", 10, 10, 50);
red.attachChild(s);



And when you need to remove all of one color...

red.detachAllChildren();



Unfortunatly that would get rid of all the red spheres, I just want to remove a section of them, I'll try to draw a diagram



RRYYBBGG

RRRYYBGR

BBRGGGBR

BBBRYYGG



R = red

Y = yellow

B = blue

G = green



I would just want to remove one section of red ie.



**YYBBGG

**YYBGR

BB
GGGBR

BBBRYYGG



also i'm pretty sure it goes into a loop because it keeps picking the last sphere it picked.



Mindgamer, to do what you have suggested I would have to rewrite, well pretty much everything I've done so far :slight_smile: as it is I've learnt a lot of things which I should do differently next time.

OH I see… Yeah I've played that game before… Let me think about it more.



EDIT:



OK, go with what MindGamer told you… my only thing to add is that you could instead do a getNeighbors() method with a bunch of if-statements and add it all to an arraylist and then remove it the way I said before… so say somebody clicks on a red sphere. The program executes the getNeighbors method for that sphere and gets the neighbors. It checks each neighbor and if it's red it adds it to the array list to remove then checks all of the neighbors of THAT sphere, etc.



Kind-of a rip-off of the AP case study this year, but it would work in this application.

I agree that it would be much (much! better done another way.



Given that code however, it looks like it would go into an infinite loop because you are adding to ballPicked while iterating through it (and getting away with it because it's synchronized I guess).



I suspect, based on your example that you keep picking up adjacent spheres and adding them, then they check for adjacent spheres and pick up the same one you just checked. It looks like you detach ballGeom inside the while block, but only set it outside.

hmm maybe it's time for a rewrite then, oh well, thanks for the help