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

2013/11/16

Tricky situation... Get the nearest object

Jonche Jonche

2013/11/16

#
Hey guys, I'm currently programming an RPG game and there's one thing missing : I want to attack the nearest enemy and none of the others. So I thought I wouuld get all the near objects, and compare them to the main character, but I believe it can be tricky if there are a lot of them, so I thought you guys could tell me one more ergonomic way of programming it. The other problem is that I can't get the class near me, so I can call methods in this class. Thanks in advance !
Gevater_Tod4711 Gevater_Tod4711

2013/11/16

#
To get the nearest objects you can use the getObjectsInRange(int, Class) method which returns all the objects within the given radius. If there is a maximum distance for the attack you can use this distance as the radius in the methodcall. This method will return a list of actors. Now you can check the distance to all of the actors near you and attack the nearest one like this:
//add this code to your player class;
public double getDistance(Actor actor) {
    return Math.hypot(actor.getX() - getX(), actor.getY() - getY());
}

public Actor getNearestActor() {
    List<Actor> nearActors = getObjectsInRange(300, Actor.class);//here you can use the radius you want and maybe another class;
    Actor nearestActor = null;
    double nearestDistance;
    double distance;
    for (int i = 0; i < nearActors.size(); i++) {
        distance = getDistance(nearestActors.get(i));
        if (distance < nearestDistance) {
            nearestActor = neareActors.get(i);
            nearestDistance = distance;
        }
    }
    return nearestActor;
}
Using this method you can get the nearest actor. Then you just need to attack this actor.
Gevater_Tod4711 Gevater_Tod4711

2013/11/16

#
Forgott to say: You need to import java.util.List to use this code. So add the code "import java.util.List;" before or after the "import greenfoot.*;" line at the top of your code.
Jonche Jonche

2013/11/19

#
I may do it wrong, I wrote this to use the methods in the attacked classes :
nearestActor.setHealth(nearestActor.healthPoints);
In which the nearestActor is, as in your code, the returned actor. The method setHealth is in main class. And the healthPoints are declared in the attacked monster.class . It doesn't work, since Greenfoot doesn't find the variables of the Actor....
danpost danpost

2013/11/19

#
'nearestActor' needs to be cast to the type of object of which class the 'setHealth' method resides to be able to access that method. So, if your moster objects are created by the Monster class, then:
Monster monster = (Monster)nearestActor;
monster.setHealth(monster.healthPoints);
Of course, setting the value of health to its current value does not produce any change in its value.
cast it to the actor it is:
((ActorClassName)nearestActor)...
Also, if you want to use it, the Distance class in my Dynamic Lighting scenario has methods to find the distances between actors, and you can find the closest and farthest actors from a different actor as well. Edit: Or do danpost's way, that's better if you are going to use the closest actor multiple times, and not just once.
Jonche Jonche

2013/11/19

#
It doesn't work... I wrote it like you did, with my classes, but it still doens't work. Here are some details that may help you : I got my subclass in the actors : Animals. There, you find some other subclasses like the subclass monster in which there are some other subclasses, that define every mob I want to spawn. Right now there is only one subclass : simple. I declared the variable healthPoints in the Monster class. the setHealth method is in the Animal class. I hope you can help me further
danpost danpost

2013/11/19

#
Do not just say you tried it; please show what you tried (providing some context).
Jonche Jonche

2013/11/19

#
if (Greenfoot.isKeyDown("space"))
       {
           if (hitReload >= hitReloadTime)
           {
             checkIfMonsterNearby();
             getNearestActor();
             Monster monster = (Monster)nearestActor;
             monster.setHealth(monster.healthPoints, damage);
             hitReload = 0;
           }
       }


public void getNearestActor()                   /**This method looks for all actors in 40px range and defines the closest one. If there are more than one, only one will be hit.**/
    {
        List<Actor> nearActors = getObjectsInRange(40, Actor.class);
        Actor nearestActor = null;
        double nearestDistance = 40;
        double distance; 
        for (int i = 0; i < nearActors.size(); i++)
        {
            distance = getDistance(nearActors.get(i));
            if (distance < nearestDistance)
            {
                nearestActor = nearActors.get(i);
                nearestDistance = distance;
            }
        }
This is what I have with the attack command on the spacebar with 50 acts reloadTime
Gevater_Tod4711 Gevater_Tod4711

2013/11/19

#
The problem is that the variable nearestActor only is visible in the getNearestActor method. To fix this you should change your code like this:
    if (Greenfoot.isKeyDown("space"))  
           {  
               if (hitReload >= hitReloadTime)  
               {  
                 checkIfMonsterNearby();  
                 Monster  monster = (Monster) getNearestActor();
                 monster.setHealth(monster.healthPoints, damage);  
                 hitReload = 0;  
               }  
           }  
      
      
    public Actor getNearestActor()                   /**This method looks for all actors in 40px range and defines the closest one. If there are more than one, only one will be hit.**/  
        {  
            List<Actor> nearActors = getObjectsInRange(40, Actor.class);  
            Actor nearestActor = null;  
            double nearestDistance = 40;  
            double distance;   
            for (int i = 0; i < nearActors.size(); i++)  
            {  
                distance = getDistance(nearActors.get(i));  
                if (distance < nearestDistance)  
                {  
                    nearestActor = nearActors.get(i);  
                    nearestDistance = distance;  
                }  
            }  
          return nearestActor;
      }
Jonche Jonche

2013/11/21

#
It works ! Thanks. Moving on the next problem : The healthPoints are set for every monster of the monster class. I need to create specific healthPoints. So I wrote this in the attack command of Joe :
if (Greenfoot.isKeyDown("space"))
       {
           if (hitReload >= hitReloadTime)
           {
             checkIfMonsterNearby();
             Monster monster = (Monster)getNearestActor();
             monster.healthPoints = setHealth(monster.healthPoints, damage);
             hitReload = 0;
           }
       }
With
public static int healthPoints; 
declared in Monster.class and
public Simple()
    {
        healthPoints = 20;
    }
defined in the simple.class subclass. Now the problem is, as already said, the healthPoints are set for every monster meaning that if I spawn more than one simple.class, they all lose health when I attack only one of them.
danpost danpost

2013/11/21

#
Remove the 'static' keyword from
public static int healthPoints;
Each monster will then have a healthPoints field of its own.
You need to login to post a reply.