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

2011/5/20

Removing Actor and Replacing it with another

roccoricciardi roccoricciardi

2011/5/20

#
Hey guys. I'm making a little Megaman vs Bass game for myself where two opponents face off as, you guessed it, Megaman and Bass. I have animated gifs (achieved via the AnimatedActor class) of the two to make the running and jumping seem more realistic. My idea was that if one were to change the direction (aka hit the left arrow key whilst facing right) then I would replace the current Actor with the a new one which would have the same methods and such as the previous, except the animated gif would be facing the opposite way. It compiles perfectly fine, but when I try to do the switch while running the program I get a crazy error, which in turn stops my program. When I hit run again the switch is carried through and I can continue playing, until I try to switch Actors again. I'll attach my Megaman codes that carry out the switch along with the insane error i keep receiving: (error): java.lang.IllegalStateException: The actor has not been inserted into a world so it has no location yet. You might want to look at the method addedToWorld on the Actor class. at greenfoot.Actor.failIfNotInWorld(Actor.java:638) at greenfoot.Actor.getOneObjectAtOffset(Actor.java:725) at Bass2.onGround(Bass2.java:84) at Bass2.checkFall(Bass2.java:74) at Bass2.act(Bass2.java:23) at greenfoot.core.Simulation.runOneLoop(Simulation.java:346) at greenfoot.core.Simulation.run(Simulation.java:178) (Megaman methods): private void placeReverse(int x, int y) { getWorld().addObject(new MegaMan2(), x, y); } private void spawnReverse() { locx = getX(); locy = getY(); placeReverse(locx,locy); getWorld().removeObject(this); } public void checkKeys() { if(Greenfoot.isKeyDown("a")) { spawnReverse(); } if(Greenfoot.isKeyDown("d")) { move(5); super.act(); } if(Greenfoot.isKeyDown("w")) { jump(); } }
roccoricciardi roccoricciardi

2011/5/20

#
PS - the "Bass2" mentioned in the error was the class trying to make the switch when the error occured
SnowRider04 SnowRider04

2011/5/20

#
I'm not entirely sure, but you might be able to use a command that just flips the image. I don't remember exact-ally how to, but if you google it, it might show up. That way you are not putting a new sprite on the character, you are just flipping the original image sheet(if you are using a sprite sheet that is). This might solve the problem, because if i understand what you have posted, you are running left with the character in its original sprite, then you go running to the right, but with a new sprite facing the way you need. i wish I could help more, but I can't seem to remember what code you need. Sorry, but good luck!
roccoricciardi roccoricciardi

2011/5/20

#
well that was my original intent, but i couldnt find anything in the API to do that so i figured a simple switch of Actors would do. If I'm reading the error correctly, there's an issue with the second Actor being put into the world, but idk how else I could accomplish that.
roccoricciardi roccoricciardi

2011/5/20

#
NEVERMIND I JUST DISCOVERED THE MIRRORHORIZONTALLY() METHOD!
roccoricciardi roccoricciardi

2011/5/20

#
that doesn't work either...it just keeps flipping horizontally everytime it acts, so megaman just glitches across the screen
davmac davmac

2011/5/20

#
It's a bit hard to tell you exactly where the problem is, since you didn't post the actual code where the exception is occurring, but, I know basically what is going wrong. After you remove the current actor from the world, you can't then continue to call various methods. The exception shows that you called "getOneObjectAtOffset" after removing the actor. This may have happened because your character just reversed direction. This is critical: once you reverse direction - that is, remove one actor and replace it with another - you mustn't perform any other actions on the old actor. For instance, in the code you did post:
public void checkKeys()
{
    if(Greenfoot.isKeyDown("a")) {
        spawnReverse();
    }
    if(Greenfoot.isKeyDown("d")) {
        move(5);
        super.act();
    }
    if(Greenfoot.isKeyDown("w")) {
        jump();
    }
}
... There is a problem because more than one key might be down. If "a" is down, you call spawnReverse(), which removes the actor from the world. Then, if "d" is down, you call move() - which is an error! An actor can't "move" if it's not in the world. You could partially fix this by returning from the method just after calling spawnReverse():
public void checkKeys()
{
    if(Greenfoot.isKeyDown("a")) {
        spawnReverse();
        return;
    }
    if(Greenfoot.isKeyDown("d")) {
        ... and so on
However, there might still be a problem in the method that calls checkKeys(). You can solve that in turn by either making sure to always call checkKeys() last (after doing everything else) or by returning a boolean from the checkKeys() method to let the caller know whether or not it is safe to perform other actions.
roccoricciardi roccoricciardi

2011/5/20

#
the keys that would be pressed after the switch are checked for in the new class's methods, so methods would be called from the mirrored megaman's class as opposed to the original that was just removed I worked on it last night and fixed my error..I'm getting a new one but that's because two buttons were being pressed at once, which is an easy fix. thanks for the help!
davmac davmac

2011/5/21

#
the keys that would be pressed after the switch are checked for in the new class's methods, so methods would be called from the mirrored megaman's class as opposed to the original that was just removed
That's not how it works... removing one actor and replacing it with another doesn't mean the code that's running will then magically apply to that second actor. It continues to run on the first actor, and any methods you call are called on the first actor, until you return from the act() method. That's why you were getting the exception.
roccoricciardi roccoricciardi

2011/5/21

#
it works fine now....as long as i don't press "left" and "right" at the same time and having my checkKeys() method at the end of my act() method made a difference, because the key it checked for was the one that "removed" that actor from the world, and "replaced" it with another, therefore the original act() method is complete, and the new act() method begins with the new actor
davmac davmac

2011/5/22

#
Ok, I think I just misunderstood what you were saying. To fix the problem when multiple keys are pressed at the same time, you should return; from the checkKeys() method once you process a key that causes the actor to be replaced.
roccoricciardi roccoricciardi

2011/5/22

#
problem fixed, now on to debugging issues with firing cannons -___-
You need to login to post a reply.