This site requires JavaScript, please enable it in your browser!
Greenfoot back
jarope
jarope wrote ...

2011/12/8

removing objects after they have been shot

jarope jarope

2011/12/8

#
Hi All, So I have followed the tutorial to shot stuff up to the point of the blob becoming a Ketchup splat. I have an object that changes from 1 actor changes after it has been hit. Using getWorld.removeObject(this); The original object disappears but my bullet keeps on flying past. Using the same getWorld.removeObject cannot be used on a class so I am a little bit stuck. What I actually need to do is have both the splat/explosion disappear and the bullet. Any advice or direction would be appreciated, I dont really want the full answer just some guidance. Thanks
davmac davmac

2011/12/8

#
Using the same getWorld.removeObject cannot be used on a class so I am a little bit stuck
You're correct that removeObject() cannot be used to remove a class, but it can remove an object. You just need to give it a reference to the object you want to remove. (If you need more help, please post your code. It makes it so much easier to explain.)
jarope jarope

2011/12/8

#
Thanks davmac Ok the code is below. So I what i was trying to do was remove (hit) after it had removed (this) in the pop() method. public class barrel extends Actor { /** * Act - do whatever the barrel wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { // Add your action code here. } public void pop() { splat hit = new splat(); getWorld().addObject(hit, getX(), getY()); getWorld().removeObject(this); } } ~~~~~~~~~~~~~~~~~AND~~~~~~~~~~~~~~~~~~ public class blob extends Actor { /** * Act - do whatever the blob wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { move(10); checkCollision(); } public void checkCollision() { barrel b =(barrel)getOneIntersectingObject(barrel.class); if (b != null) b.pop(); } }
jarope jarope

2011/12/8

#
Ok, a few more looks at the documentation etc and I found this which I think may well answer my question. http://www.greenfoot.org/scenarios/2358 From your good self davmac regards Jarope
davmac davmac

2011/12/8

#
Ok, I hope that helps. I have to admit I don't understand exactly what the problem is:
So I what i was trying to do was remove (hit) after it had removed (this) in the pop() method
... but you are adding hit in the pop() method. Why would you want to remove it again immediately?
davmac davmac

2011/12/8

#
Did you mean you want to remove the blob when it hits a barrel? Then you should edit the blob code, checkCollision() method:
public void checkCollision()
{
    barrel b =(barrel)getOneIntersectingObject(barrel.class);
    if (b != null) {
        b.pop();
        getWorld().removeObject(this);
    }
}
(Also, convention in Java is to have class names start with a capital letter! It might not matter to you now, but it is quite confusing for others - i..e me - to read if they start with a lower case letter).
jarope jarope

2011/12/8

#
Thank You for the replies. Yes looking at your code I could see the need to make my class names uppercase. Basically the blob (bullet) needs to disappear yes. I am going to rewrite this and then get back if there are any further issues. Thanks for your help. jarope
jarope jarope

2011/12/8

#
thanks to davmac some progress :¬) But that was in my test world with completely new actors and everything fresh. Now I am trying to apply the working test code to a pre supplied scenario. It is this pre supplied scenario that had lower case ClassNames, so thanks for the correction davmac I have applied this change to the scenario as well and provided UpperCaseClassNames. Applying my movement and fire() method to the Robot, I have ended up with a shot out the back of the Robot that rather affectively blows up whatever is there (kinda like a power gas). What is not happening is that the shot is not moving forward. In the test world after the shot was instantated(?) I applied move(10); but this scenario seems to have other ideas about what move does. It also has forward(int); but only in the Robot class so I tried call that with ClassName objectName = new ClassName(); i.e Robot gogo = new Robot(); gogo.forward(1); I guess I am missing something simple here, but sorry I'm new to this. any points Greenfoot Guru's would be most appreciated. My code: //////////////////////////// ///// Robot.class \\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ public class Robot extends Actor { private static final int EAST = 0; private static final int WEST = 1; private static final int NORTH = 2; private static final int SOUTH = 3; private int direction; public Robot() { setDirection(EAST); } public void act() { if(endItNow()==true) { Greenfoot.stop(); } else { if(Greenfoot.isKeyDown("left")) { setDirection(WEST); forward(1); } if(Greenfoot.isKeyDown("right")) { setDirection(EAST); forward(1); } if(Greenfoot.isKeyDown("up")) { setDirection(NORTH); forward(1); } if(Greenfoot.isKeyDown("down")) { setDirection(SOUTH); forward(1); } if("space".equals(Greenfoot.getKey())) { fire(); } //put your code here } } public void fire() { int gogo = getX(); Shot shot = new Shot(); getWorld().addObject(shot, getX(), getY()); shot.setLocation (getX(),getY()); } public void setDirection(int direction) { this.direction = direction; switch(direction) { case SOUTH : setRotation(90); break; case EAST : setRotation(0); break; case NORTH : setRotation(270); break; case WEST : setRotation(180); break; default : break; } } public void turnLeft() { switch(direction) { case SOUTH : setDirection(EAST); break; case EAST : setDirection(NORTH); break; case NORTH : setDirection(WEST); break; case WEST : setDirection(SOUTH); break; } } public void turnRight() { switch(direction) { case SOUTH : setDirection(WEST); break; case EAST : setDirection(SOUTH); break; case NORTH : setDirection(EAST); break; case WEST : setDirection(NORTH); break; } } public boolean canMove() { World myWorld = getWorld(); int x = getX(); int y = getY(); // test for outside border if (x >= myWorld.getWidth() || y >= myWorld.getHeight()) { return false; } else if (x < 0 || y < 0) { return false; } return true; } public void forward(int howMany) { for(int loop=0;loop<howMany;loop++) { fwd(); } } public void backward(int howMany) { for(int loop=0;loop<howMany;loop++) { bwd(); } } public void bwd() { if (!canMove()) { return; } switch(direction) { case SOUTH : setLocation(getX(), getY() - 1); break; case EAST : setLocation(getX() - 1, getY()); break; case NORTH : setLocation(getX(), getY() + 1); break; case WEST : setLocation(getX() + 1, getY()); break; } } public void fwd() { if (!canMove()) { return; } switch(direction) { case SOUTH : setLocation(getX(), getY() + 1); break; case EAST : setLocation(getX() + 1, getY()); break; case NORTH : setLocation(getX(), getY() - 1); break; case WEST : setLocation(getX() - 1, getY()); break; } } public boolean checkBumpers() { Actor wall = getOneObjectAtOffset(0, 0, wall.class); if(wall!=null) { return true; } else { return false; } } public boolean endItNow() { Actor end_ = getOneObjectAtOffset(0, 0, end_.class); if(end_ != null) { return true; } else { return false; } } } ///////////////////////////// ////// Shot.class \\\\\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ public class Shot extends Actor { /** * Act - do whatever the Shot wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { checkCollision(); } public void checkCollision() { Wall b=(Wall)getOneIntersectingObject(Wall.class); if (b != null) b.pop(); getWorld().removeObject(this); // Removes the Shot } } /////////////////////////////// ///////// Wall.class \\\\\\\\\\\ \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ public class Wall extends Actor { /** * Act - do whatever the wall wants to do. This method is called whenever * the 'Act' or 'Run' button gets pressed in the environment. */ public void act() { // Add your action code here. again, please do not add here. } public void pop() { Blast hit = new Blast(); getWorld().addObject(hit, getX(), getY()); getWorld().removeObject(this); // removes the Wall } }
davmac davmac

2011/12/9

#
What is not happening is that the shot is not moving forward. In the test world after the shot was instantated(?) I applied move(10); but this scenario seems to have other ideas about what move does
What do you mean by "other ideas"? I would have though move() (in the Shot class' act method) would be exactly what you need.
jarope jarope

2011/12/10

#
Hi and thanks for reply. I now have the shot going forward. BUT - rather than hit any object of the correct type it goes to the world edge and hits that the explosion works and the images change as expected. So for some reason it seems that it is jumping to the edge of the world and not moving across the grid 1 block at a time. as you can see the Robot class has the forward() and fwd() sections set up and I wonder if they are causing move() to use different units?? I have successfully followed the tutorial in a new world with no issues so feel it must be something in the scenario that has been created for us. Thanks again
davmac davmac

2011/12/10

#
I don't have your latest code so can't really say what's wrong, but I can tell you that nothing in the Robot class can affect the way a Shot moves. Perhaps it's simply that the speed is too high.
jarope jarope

2011/12/12

#
Hi, OK link to latest version is here Latest Code I think the issue with how far / fast the actor Shot is moving is down to the scale of the grid. I tried changing the size of the grid in the world on a test world and was able to duplicate the situation. So what happens is with the world grid set to 600,400,1 the Shot moves as expected. But with the World set to 30,30,50 it just jumps to the edge of the world. I cant change the world size as that would be altering the scenario we have to work with to much. So should a scaling on the move(); method work? Something like move(1/50); jarope
davmac davmac

2011/12/12

#
So should a scaling on the move(); method work? Something like move(1/50);
Unfortunately it won't work in this case for two reasons: firstly, the move method takes an "int" parameter, i.e. a whole number. There is no way to pass in a fraction. Also, there is a bug in the way move(...) is implemented in the current version of Greenfoot. In worlds where the cell size is greater than 1, move(...) actually moves too far. You can work around this by using setLocation(...) and figuring out the coordinates manually. In fact, you can even override Greenfoot's move(...) method with your own, which works correctly:
    public void move(int distance)
    {
        double radians = Math.toRadians(rotation);

        // We round to the nearest integer, to allow moving one unit at an angle
        // to actually move.
        int dx = (int) Math.round(Math.cos(radians) * distance);
        int dy = (int) Math.round(Math.sin(radians) * distance);
        setLocation(getX() + dx, getY() + dy);
    }
jarope jarope

2011/12/12

#
I thought that move had an issue as it was shown in the "shooting" tutorials as being a double. but that explains also why in a new world with no changes why it worked and with the scenario given there was a problem. will work through this and see what results I get. again, Many thanks Jarope
You need to login to post a reply.