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

2018/6/5

getIntersectingObjects - Enemy takes Damage from Bullet

fabipfolix fabipfolix

2018/6/5

#
Hello, In my program I got a guy that can shoot with different weapons(->different damage) at Enemies. The damage variable is stored in the bullet. If a subclass of the Enemy-class get hit by the bullet it should decrease the enemies hp.
public void hitEnemy(){
        if(isTouching(Enemy.class)){
            List<Enemy> enemies = getIntersectingObjects(Enemy.class);
            Enemy enemy = enemies.get(0);
            enemy.gotDmg(dmg);
        }
    }
I guess the problem is this part, but I don't know how to replace it:
List<Enemy> enemies = getIntersectingObjects(Enemy.class);
            Enemy enemy = enemies.get(0);
danpost danpost

2018/6/5

#
You can avoid explicitly creating a List object altogether with this:
public void hitEnemy(){
    if(isTouching(Enemy.class)){
        Enemy enemy  = (Enemy) getIntersectingObjects(Enemy.class).get(0);
        enemy.gotDmg(dmg);
    }
}
fabipfolix fabipfolix

2018/6/5

#
danpost wrote...
You can avoid explicitly creating a List object altogether with this:
public void hitEnemy(){
    if(isTouching(Enemy.class)){
        Enemy enemy  = (Enemy) getIntersectingObjects(Enemy.class).get(0);
        enemy.gotDmg(dmg);
    }
}
If i try to shoot now, I get this Error: java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed. at greenfoot.Actor.failIfNotInWorld(Actor.java:681) at greenfoot.Actor.isTouching(Actor.java:943) at Bullet.hitEnemy(Bullet.java:38) at Bullet.<init>(Bullet.java:20) at Player.shoot(Player.java:134) at Player.checkKeypress(Player.java:65) at Player.act(Player.java:34) at greenfoot.core.Simulation.actActor(Simulation.java:594) at greenfoot.core.Simulation.runOneLoop(Simulation.java:552) at greenfoot.core.Simulation.runContent(Simulation.java:215) at greenfoot.core.Simulation.run(Simulation.java:205) Unfortunately i can't upload the Scenario, because it's to big.
danpost danpost

2018/6/5

#
fabipfolix wrote...
If i try to shoot now, I get this Error: << Error Omitted >> Unfortunately i can't upload the Scenario, because it's to big.
You cannot call hitEnemy from the constructor of the class. Show full Bullet class for further assistance.
fabipfolix fabipfolix

2018/6/5

#
danpost wrote...
fabipfolix wrote...
If i try to shoot now, I get this Error: << Error Omitted >> Unfortunately i can't upload the Scenario, because it's to big.
You cannot call hitEnemy from the constructor of the class. Show full Bullet class for further assistance.
Oh, I overlooked that but now I fixed it and got the next error, after shooting at the Enemy and try to remove it. Here's the complete Bullet class:
import greenfoot.*;
import java.util.List;

public class Bullet extends Actor{
 
    public int dmg;
    
    public Bullet(int rotation, int damage){
        MouseInfo mouse = Greenfoot.getMouseInfo();
        
        setRotation(rotation);
        dmg = damage;
    }
    
    public void act() 
    {
        hitEnemy();
        move(30);
        if(isAtEdge()){
            getWorld().removeObject(this);
        }
        
    }   
    
    public void hitEnemy(){
        if(isTouching(Enemy.class)){
            Enemy enemy  = (Enemy) getIntersectingObjects(Enemy.class).get(0);
            enemy.gotDmg(dmg);
            try{
                getWorld().removeObject(this);
            }catch(Exception e){}
        }
    }
}
And here's the Error if the Bullet is touching the Enemy: java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed. at greenfoot.Actor.failIfNotInWorld(Actor.java:681) at greenfoot.Actor.isAtEdge(Actor.java:254) at Bullet.act(Bullet.java:29) at greenfoot.core.Simulation.actActor(Simulation.java:594) at greenfoot.core.Simulation.runOneLoop(Simulation.java:552) at greenfoot.core.Simulation.runContent(Simulation.java:215) at greenfoot.core.Simulation.run(Simulation.java:205)
danpost danpost

2018/6/5

#
Remove lines 2 and 9 (neither used and 9 misplaced). Remove the "try-catch" structure around line 30 (leave line 30). Note that the actor will definitely be in the world at the time line 30 executes. Change line 19 to this:
if (getWorld() != null && isAtEdge()){
Note the there is a possibility that the actor is not in the world at this time because an enemy may have been hit and this actor may have been removed from the world. Therefore, a check to ensure the actor is still in the world was added.
fabipfolix fabipfolix

2018/6/5

#
Thank you, that problems seems to be solved. But in the enemy class I got the int hp and the method gotDmg(). And if I'm shooting at a subclass Object the hp defined in the subclass get decreased and the object doesn't get removed, because the hidden hp inherited from the Enemy-Class got still the value defined in the Enemy-Class. Enemy:
import greenfoot.*;

public class Enemy extends Actor{
   
    int hp;
    
    public void act(){
        if(hp>=0){
            getWorld().removeObject(this);
        }
    }  

    public void gotDmg(int dmg){
        hp=hp-dmg;
        if(hp>=0){
            getWorld().removeObject(this);
        }
       
    }   
    
}
Dragon:
import greenfoot.*;

public class Dragon extends Enemy{
    
    public void act() {
        
    }   
    
    public void gotDmg(int dmg){
        hp=hp-dmg;
        if(hp>=0){
            getWorld().removeObject(this);
        }      
    }
}
danpost danpost

2018/6/5

#
Remove lines 5 through 14 in the Dragon class (and similar for other subclasses). The act method of Enemy will then run for any dragon objects and all damage for ANY subclass object can be directed to the Enemy class. In the Enemy class, the act method does not need to check for all damage taken. That is (at least an attempt of it) done in the gotDmg method. Only problem there is the conditional operator, which currently says to remove the actor if it can still take some damage.
fabipfolix fabipfolix

2018/6/5

#
I did that, but in the end it didn't changed something. Enemy:
import greenfoot.*;

public class Enemy extends Actor{
   
    int hp;
    
    public void act(){
    }  
    
    
    public void gotDmg(int dmg){
        hp=hp-dmg;
        if(hp>=0){
            getWorld().removeObject(this);
        }     
    }
}
Dragon:
import greenfoot.*;
public class Dragon extends Enemy
{
    int hp = 100; 
}
That is what you said, isn't it? But the dragon still doesn't die: Picture Now the hidden hp are below 0 but the hp of the dragon class are still 100.
danpost danpost

2018/6/6

#
Remove line 4 from Dragon class. To set damage to 100, add this to Dragon class:
public Dragon()
{
    hp = 100;
}
fabipfolix fabipfolix

2018/6/6

#
I still don't get it. Now the Dragon instantly dies after one hit. If I add anything, like a System.out.println("xy"); to the hitEnemy()-Method i'll get this Error: java.lang.IllegalStateException: Actor not in world. An attempt was made to use the actor's location while it is not in the world. Either it has not yet been inserted, or it has been removed. at greenfoot.Actor.failIfNotInWorld(Actor.java:681) at greenfoot.Actor.getIntersectingObjects(Actor.java:915) at Bullet.hitEnemy(Bullet.java:28) at Bullet.act(Bullet.java:17) at greenfoot.core.Simulation.actActor(Simulation.java:594) at greenfoot.core.Simulation.runOneLoop(Simulation.java:552) at greenfoot.core.Simulation.runContent(Simulation.java:215) at greenfoot.core.Simulation.run(Simulation.java:205) Bullet:
import greenfoot.*;

public class Bullet extends Actor{
 
    public int dmg;
    MouseInfo mouse = Greenfoot.getMouseInfo();
    
    public Bullet(int rotation, int damage){
        
        
        setRotation(rotation);
        dmg = damage;
    }
    
    public void act() 
    {
        hitEnemy();
        move(30);
        if(getWorld() != null && isAtEdge()){
            getWorld().removeObject(this);
        }
        
    }   
    
    public void hitEnemy(){
        if(isTouching(Enemy.class)){
            System.out.println("xy");
            Enemy enemy  = (Enemy) getIntersectingObjects(Enemy.class).get(0);
            enemy.gotDmg(dmg);
            
            getWorld().removeObject(this);
            
        }
    }
}
Enemy:
import greenfoot.*;

public class Enemy extends Actor{
   
    int hp;
    
    public void act(){
    }  
    
    
    public void gotDmg(int dmg){
        hp=hp-dmg;
        if(hp>=0){
            getWorld().removeObject(this);
        }     
    }
}
Dragon:
import greenfoot.*;
public class Dragon extends Enemy
{
    public Dragon(){
        hp=10000;
    }
}
danpost danpost

2018/6/6

#
Line 13 in your Enemy class is still asking the wrong thing.
danpost wrote...
In the Enemy class, the act method does not need to check for all damage taken. That is (at least an attempt of it) done in the gotDmg method. Only problem there is the conditional operator, which currently says to remove the actor if it can still take some damage.
fabipfolix fabipfolix

2018/6/6

#
danpost wrote...
Line 13 in your Enemy class is still asking the wrong thing.
danpost wrote...
In the Enemy class, the act method does not need to check for all damage taken. That is (at least an attempt of it) done in the gotDmg method. Only problem there is the conditional operator, which currently says to remove the actor if it can still take some damage.
And how can I solve this problem?
danpost danpost

2018/6/6

#
fabipfolix wrote...
And how can I solve this problem?
Change the conditional operator (currently ">=") to something more appropriate.
fabipfolix fabipfolix

2018/6/6

#
danpost wrote...
fabipfolix wrote...
And how can I solve this problem?
Change the conditional operator (currently ">=") to something more appropriate.
Thank you, i missed, that it was the false one ^^ Now it's working :D
You need to login to post a reply.