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

2022/11/12

How can I remove a specific actor, depending on the location of it and another actor (shooting with penetration)?

1
2
Tidali Tidali

2022/11/12

#
Disclaimer: I am german, you can answer in german. I also use a lot of public variables and no getter and setter, but "((MyWorld)getWorld()).variable" instead, because it is simpler for me right now. I know it's bad. (If it makes my whole game easier you can also give me tips on how to use them in this scenario, but it's not my question here). Heyho Greenfoot Community, I need help with tracking 2 interacting actors and change variables of them. /////////////I will be marking specific question by commenting them like this///////////// I am currently working on a Top Down shooter and I am currently facing the challenge of programming variable penetrating bullets. I have my character "joeMama"(joeMama.class), who shoots "e1" (e1.class, meaning enemy1) with "ball" (ball.class). joeMama will try to shoot the "e1" by spawning "ball" with a specific cooldown on left click (already working). The ball will do the following on collision:
public class ball extends Actor
{
    /**
     * Act - do whatever the ball wants to do. This method is called whenever
     * the 'Act' or 'Run' button gets pressed in the environment.
     */
    
    private boolean toBeDeleted=false;
    private int bulletMoveSpeed=25;
    public int initialBulletHP=1,bulletHP;
    private int hitboxE1=40;
    int i=1;
    public ball(){
    }
    public void act()
    {   
        for(int i=1;i==1;i++){
            initialBulletHP=((MyWorld)getWorld()).buDa;
            bulletHP=initialBulletHP;
        }
        if(((MyWorld)getWorld()).wIP==false){
            move(bulletMoveSpeed);
        }
        if(this.isAtEdge()&&this!=null)this.toBeDeleted=true;
        if(this.toBeDeleted==true){
            getWorld().removeObject(this);
            i++;
        }
        if(i==1){    
            Actor intObj = getOneIntersectingObject(e1.class);
            if(intObj!=null){
                do{
                    Actor intObj2 = getOneIntersectingObject(e1.class);
                    this.bulletHP--;
                    ((MyWorld)getWorld()).getObjects(e1.class).get(0).e1Health--;
                    if(((MyWorld)getWorld()).getObjects(e1.class).get(0).e1Health<=0)break;
                    if(this.bulletHP==0)break;
                }while(this.bulletHP>0);
            }
            if(this.bulletHP<=0)this.toBeDeleted=true;
        }
    }
}
What I am trying to achieve is, that not every act-cycle both parties are reduced by 1 healthpoint, but in an instance, so the "ball" will further move after reducing the "e1's" health to zero and only after the clash has happened and not while it is happening. When only dealing one damage the do-while is working, but as soon, as I add damage it gets weird. Adding damage in this sense means adding a point to bulletHP. The do-while will act one more time for each bulletHP, so it makes sense. What happens though is, that other instances than the "e1" that is shoot will be taking damage. /////////////How can I make the "ball" make a list of nearby "e1" on contact with one, change the variable "e1Health" of the first "e1" in the list, depending on range, and delete the list upon making the "e1" disappear.//////////////// I am also welcoming alternatives, but I would have thought of this as one of the best solutions. Code of the "e1":
public class e1 extends enemies
{
    private int range = 2000, moveSpeed=1;
    public int e1Damage=12, e1Health=3, e1Worth=10;
    public int e1XPgivings; //how much XP u gain
    public int spawnImmunity=10;
    public boolean toBeDeleted=false;
    GreenfootImage lobster = new GreenfootImage("lobster.png");
     
    public void e1(){
        setImage(lobster);
    }
     
    public void act()
    {
        if(spawnImmunity>0)spawnImmunity--;
        if(((MyWorld)getWorld()).wIP==false){ //important for pause, almost every actor and the world has most methods only active when the game isn't paused
            movement();
            damageCalc();
        }
        if(this.toBeDeleted==true)this.getWorld().removeObject(this);
    }
    public void movement(){
        if (!getObjectsInRange( range, joeMama.class ).isEmpty()){
            Actor jM = getObjectsInRange(range,joeMama.class ).get(0);
            turnTowards( jM.getX(), jM.getY());
        }
        move(this.moveSpeed);
        Actor bullet = getOneIntersectingObject(ball.class);
        Actor player = getOneIntersectingObject(joeMama.class);
        if(player != null){
            ((MyWorld)getWorld()).playerHealth-=e1Damage+e1Health*2;
            ((MyWorld)getWorld()).regCd=((MyWorld)getWorld()).regMaxCd; //irrelevant
            this.toBeDeleted=true;
        }
    }
    public void damageCalc(){
        if(spawnImmunity<=0){
            this.e1XPgivings=Greenfoot.getRandomNumber(6)+4;
            if(this.e1Health<=0||this.toBeDeleted==true){
                ((MyWorld)getWorld()).scorePoints+=e1Worth;
                ((MyWorld)getWorld()).pcX+=e1XPgivings;
                this.toBeDeleted=true;
            }
        }
    }
}
My best try is something like this, but I couldn't find how to code it:
Actor ne1 = getObjectsInRange(exampleSizeOfE1,e1.class ).get(0); //nearest enemy in range

//then something like this:
if(ne1!=null){
((MyWorld)getWorld()).getActor(ne1).e1Health--;
}
I will probably edit things, please ask if you need more to know more. Thanks for answers in advance!
danpost danpost

2022/11/13

#
Maybe, have a ball keep track of any enemy encountered until it is no longer in the world or possibly another one comes closer (or something along those lines). This would entail having the reference set to null when no enemies are in range. Also, a check that the enemy encountered is still in the world would also need to be checked (so the reference can be set back to null).
Tidali Tidali

2022/11/13

#
I will surely try that, thanks. Do you know how to get access of a variable of a specific instance of an actor? Like this:
Actor ne1 = getObjectsInRange(exampleSizeOfE1,e1.class ).get(0); //nearest enemy in range
 
//then something like this:
if(ne1!=null){
((MyWorld)getWorld()).getActor(ne1).e1Health--;
}
this doesn't work but I think it's just a syntax problem?
Super_Hippo Super_Hippo

2022/11/13

#
What is ‘getActor’? With the first line, you get a reference to the actor already. The ‘e1Health’ variable you try to change is not defined in Actor, but in a subclass. So the way it can work is to change the ‘ne1’ variable from type ‘Actor’ to ‘e1’ and then do ‘ne1.e1Health--’.
Tidali Tidali

2022/11/13

#
Super_Hippo wrote...
What is ‘getActor’? With the first line, you get a reference to the actor already. The ‘e1Health’ variable you try to change is not defined in Actor, but in a subclass. So the way it can work is to change the ‘ne1’ variable from type ‘Actor’ to ‘e1’ and then do ‘ne1.e1Health--’.
Uhh could you write this as a short code, I don't rlly get what you mean, sorry
danpost danpost

2022/11/14

#
Tidali wrote...
I think it's just a syntax problem?
Well, how does the getActor method in your MyWorld class work? Show it's codes.
Tidali Tidali

2022/11/17

#
danpost wrote...
Tidali wrote...
I think it's just a syntax problem?
Well, how does the getActor method in your MyWorld class work? Show it's codes.
Oh I don't have any method, bcs that is exactly what I am searching for. It was just an example how to get the variable of the nearest actor. getActor doesn't exist. getObject does.
danpost danpost

2022/11/18

#
Tidali wrote...
Oh I don't have any method, bcs that is exactly what I am searching for. It was just an example how to get the variable of the nearest actor. getActor doesn't exist. getObject does.
You could use getWorld().getObjects(e1.class) to get the list of that type actor in the world. Then, go through the list to determine which is closest, if any existed in the world. Then, cast the closest to its type and grab the value of the variable required (ex. int value = ((e1)closest).variableName; )
Tidali Tidali

2022/11/19

#
danpost wrote...
Tidali wrote...
Oh I don't have any method, bcs that is exactly what I am searching for. It was just an example how to get the variable of the nearest actor. getActor doesn't exist. getObject does.
You could use getWorld().getObjects(e1.class) to get the list of that type actor in the world. Then, go through the list to determine which is closest, if any existed in the world. Then, cast the closest to its type and grab the value of the variable required (ex. int value = ((e1)closest).variableName; )
I get the idea, but could you - if you have time - code it for me, please? I don't know how to this one. Thanks!
Super_Hippo Super_Hippo

2022/11/20

#
I think it would make sense for you to show what you try in order to learn how to do it. My last message for example was a pretty clear description and I told you everything you needed to change exactly – not to get the nearest one, but at least get any one and fix the syntax issues to have a start.
Tidali Tidali

2022/11/20

#
Actor intObj = getOneIntersectingObject(e1.class);
            if(intObj!=null){
                do{
                    this.bulletHP--;
                    ((MyWorld)getWorld()).intObj.e1Health--;
                    if(((MyWorld)getWorld()).intObj.e1Health<=0)break;
                    if(this.bulletHP==0)break;
                }while(this.bulletHP>0);
            } 
I tried it like this and like this, both are wrong.
Actor intObj = getOneIntersectingObject(e1.class);
            if(intObj!=null){
                do{
                    this.bulletHP--;
                    intObj.e1Health--;
                    if(intObj.e1Health<=0)break;
                    if(this.bulletHP==0)break;
                }while(this.bulletHP>0);
            }  
I know I dont need the " if(this.bulletHP==0)break;" but I left it in for now.
Super_Hippo Super_Hippo

2022/11/20

#
Ok. Discard the first option. Use the second one. In line 1, change Actor to e1. Otherwise you can’t use functions or variables you defined in that class. I wonder what you are trying to achieve with the do-while. It might not work as you want it to work.
Tidali Tidali

2022/11/21

#
Super_Hippo wrote...
I wonder what you are trying to achieve with the do-while. It might not work as you want it to work.
So the idea is that my bullets "ball" can be increased in damage and pierce enemies that have low enough hitpoints. For example I give the "ball" an hp value "bulletHP" of 5. The inital health value of every "e1" is 3. If the ball kills the enemy, the enemy's supposed to disappear and the ball continues on it's path with 2 hp left, until it is destroyed or touches the edge of the map. When the "ball" intersects with any instance of the enemy "e1", I want the do-while to reduce the hp value of both the ball and the enemy by 1 every loop until atleast one of them reaches zero. This has to be in a do-while, because otherwise, the ball would move while this is counted and could possibly leave the hitbox of the enemy without killing it or being destroyed. I don't want that to happen (atleast right now, that would actually be an interesting thought).
Tidali Tidali

2022/11/21

#
Super_Hippo wrote...
In line 1, change Actor to e1. Otherwise you can’t use functions or variables you defined in that class.
e1 intObj = getOneIntersectingObject(e1.class);
It says at e1.class greenfoot.Actor cannot be converted to e1
Super_Hippo Super_Hippo

2022/11/21

#
Ah great, Greenfoot still didn’t change that :( Try this:
e1 intObj = (e1) getOneIntersectingObject(e1.class);
Tidali wrote...
When the "ball" intersects with any instance of the enemy "e1", I want the do-while to reduce the hp value of both the ball and the enemy by 1 every loop until atleast one of them reaches zero. This has to be in a do-while, because otherwise, the ball would move while this is counted and could possibly leave the hitbox of the enemy without killing it or being destroyed. I don't want that to happen (atleast right now, that would actually be an interesting thought).
Ok, I understand now. I think it would be the best to reduce the health of both by the lower health so there is no need to loop.
There are more replies on the next page.
1
2