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

2014/12/14

Get nearest Object

ds06 ds06

2014/12/14

#
Hello, i try do code a method which spawns a bullet at the position of the player and then move to the nerest Object of a given class.
if(Greenfoot.isKeyDown("1") && !cd1){

                if(!getObjectsInRange(350, Enemy1.class).isEmpty()){
                    Actor target= (Enemy1) getObjectsInRange(350, Enemy1.class).get(0);
                    Actor bullet = new Bullet();
                    ((Main)getWorld()).addObject(bullet, getX(), getY());
                    bullet.turnTowards(target.getX(), target.getY());
                    bullet.setImage("frost.png");
                    
                    cd1counter = 80;
                    cd1=true;

                }
            }
It works if there is one Object of the Enemy1.class on the World, but if there is a second and im nearer it it, the bullet still moves to the other Object. Thanks in advance Sven
danpost danpost

2014/12/14

#
You could use a local int variable to hold the distance (now hardcoded as '350') so you can vary it. Make it smaller and smaller until no objects are found (use a 'while' loop). Then increment it and get the object.
ds06 ds06

2014/12/14

#
and how? getObjectsInRange stores the Objects it got in a list, doesnt it? Isnt that list sorted? get(0) should then give me the nearest object?
danpost danpost

2014/12/14

#
ds06 wrote...
getObjectsInRange stores the Objects it got in a list, doesnt it? Isnt that list sorted? get(0) should then give me the nearest object?
No -- the list is not sorted. You can go through the list and determine the closest one by using the distance formula.
ds06 ds06

2014/12/14

#
danpost wrote...
ds06 wrote...
getObjectsInRange stores the Objects it got in a list, doesnt it? Isnt that list sorted? get(0) should then give me the nearest object?
No -- the list is not sorted. You can go through the list and determine the closest one by using the distance formula.
I got it to work :)
if(Greenfoot.isKeyDown("1") && !cd1){

                if(!getObjectsInRange(350, Enemy1.class).isEmpty()){
                    int dist=350;
                   
                    while(!getObjectsInRange(dist, Enemy1.class).isEmpty()){
                        dist--;
                    }
                    dist++;

                    Actor target = (Enemy1) getObjectsInRange(dist,Enemy1.class).get(0);

                    Actor bullet = new Bullet();
                    ((Main)getWorld()).addObject( bullet,((Main)getWorld()).one.getX(), ((Main)getWorld()).one.getY());
                    bullet.turnTowards(target.getX(), target.getY());
                    bullet.setImage("frost.png");

                    System.out.println("cd1anfang");
                    cd1counter = 80;
                    cd1=true;

                }
            }
Thanks for your help, youre awesome!
ds06 ds06

2014/12/14

#
While we are at it: How can i test if the bullet collide with target? I tried something like this:
public class Bullet extends Klassen
{
    
    public void act() 
    {
        move(10);
        
        if(this.intersects(Klassen.target)){
            getWorld().removeObject(this);
        }
        
    }
    
   

}
But i got non-static variable target cannot be referenced from a static context. Usuallay i know how to fix that, but not in this case..
danpost danpost

2014/12/14

#
If you want the 'target' that the bullet was created for to be checked on, then you should probably have the bullet keep a reference to it (make it a smart bullet by passing the target to the bullet constructor and have the constructor save it in a reference field. Then use that reference instead of 'Klassen.target', which is meaningless as 'target' was local to the method in the Klassen class.
danpost danpost

2014/12/14

#
Also, I noticed that you have the Bullet class extending Klassen. That cannot be good. Klassen is for your player(s) and a bullet is not a player. Have the Bullet class extend Actor or, if you really want it to subclass something else, create a Projectile class where Bullet, Shot, Missile, Cannonball or whatever, provided it is a projectile, can extend it. Subclassing is a way to be more specific in describing a type of object.
ds06 ds06

2014/12/15

#
danpost wrote...
If you want the 'target' that the bullet was created for to be checked on, then you should probably have the bullet keep a reference to it (make it a smart bullet by passing the target to the bullet constructor and have the constructor save it in a reference field. Then use that reference instead of 'Klassen.target', which is meaningless as 'target' was local to the method in the Klassen class.
Yes thats what its supposed to do. But i dont know how i can get the Actor target form Klassen referenced in Bullet. Do i have to "send" the Actor to the Bullet? Or how can i get it in Bullet?
danpost wrote...
Also, I noticed that you have the Bullet class extending Klassen. That cannot be good. Klassen is for your player(s) and a bullet is not a player. Have the Bullet class extend Actor or, if you really want it to subclass something else, create a Projectile class where Bullet, Shot, Missile, Cannonball or whatever, provided it is a projectile, can extend it. Subclassing is a way to be more specific in describing a type of object.
Youre right, it wasnt a subclass from Klassen, but i tried to test something. Its now normal class.
danpost danpost

2014/12/15

#
Well, you already had a reference to it when you created the bullet -- just pass it to the new bullet via its constructor call (add a parameter to hold the actor, pass the target in the constructor call and have the bullet constructor save the target in an instance field).
ds06 ds06

2014/12/15

#
danpost wrote...
Well, you already had a reference to it when you created the bullet -- just pass it to the new bullet via its constructor call (add a parameter to hold the actor, pass the target in the constructor call and have the bullet constructor save the target in an instance field).
Something like this?
if(Greenfoot.isKeyDown("1") && !cd1){

                if(!getObjectsInRange(350, Enemy1.class).isEmpty()){
                    int dist=350;
                   
                    while(!getObjectsInRange(dist, Enemy1.class).isEmpty()){
                        dist--;
                    }
                    dist++;

                    Actor target = (Enemy1) getObjectsInRange(dist,Enemy1.class).get(0);

                    Actor bullet = new Bullet(target); //send target to Bullet
                    ((Main)getWorld()).addObject( bullet,((Main)getWorld()).one.getX(), ((Main)getWorld()).one.getY());
                    bullet.turnTowards(target.getX(), target.getY());
                    bullet.setImage("frost.png");
                    
                    System.out.println("cd1anfang");
                    cd1counter = 80;
                    cd1=true;

                }
            }
And Bullet:
public class Bullet extends Actor

{

    public Bullet(Actor a){
        Actor active =a;
    }

    public void act() 
    {
        move(10);

        if(this.intersects(active)){
            getWorld().removeObject(this);
        }

    }


}
I get cannot find symbol - variable active
danpost danpost

2014/12/15

#
The field must be declared outside the method:
public class Bullet extends Actor
{
    Actor active;

    public Bullet(Actor a)
    {
        active = a;
    }
    // etc.
Otherwise, the value is lost when the constructor finishes execution.
ds06 ds06

2014/12/15

#
Great it works now :) I had "private Actor active;", and that didnt work.
danpost danpost

2014/12/15

#
ds06 wrote...
Great it works now :) I had "private Actor active;", and that didnt work.
'private Actor active;' should work. Maybe you tried that inside the constructor and not outside of it.
ds06 ds06

2014/12/15

#
Oddly, this works now too :D Maybe i misspelled. Thanks again for your help!
You need to login to post a reply.