Loading...
Logo
Processing Forum

More errors to be fixed

in Programming Questions  •  7 months ago  
Hi,
This problem has mainly to do with ArrayLists; I really don't know how to use them. I've had to scrap a project that I spent a nice amount of time on because ArrayLists didn't co-operate, and I think I'm scrapping the next one. My inability to work with them has basically stopped me from learning how to code more complicated things. So, before I scrap this project, I was wondering if anyone knew how to fix the problems I made. Basically, I'm stuck on getting the mover (myFirstMover, from the class Mover) to go towards an ArrayList of "targets," (Classes Target and TargetManager) the first one being the mouse (Class MousePointer). Sadly, I can't give you much information on why the problem is happening, other than a nullPointerError in void Behavior in the Mover class, and probably the Mover just not going towards the mouse (If my current luck holds out). Again, I'm sorry for the probably very obvious error.
Anyways, here's the code:

Main sketch:

Copy code
  1. Mover myFirstMover;
  2. TargetManager tManager;
  3. MousePointer pointer;
  4. void setup() {
  5.   frameRate(15);
  6.   myFirstMover = new Mover(width/2,height/2);
  7.   tManager = new TargetManager();
  8.   pointer = new MousePointer();
  9.   size(300,300);
  10. }
  11. void draw() {
  12.   background(0);
  13.   myFirstMover.Display();
  14.   myFirstMover.Update();
  15.   myFirstMover.Movement();
  16.   myFirstMover.Emoticon();
  17.   myFirstMover.Behavior();
  18.   tManager.Manage();
  19.   pointer.Display();
  20.   pointer.Update();
  21. }

Mover class:

Copy code
  1. import java.util.Iterator;
  2. class Mover { //Class for the movers
  3.   PVector location,targetLocation; //Location of the mover, and of the target location
  4.   float hungerLevel,thirstLevel,happinessLevel; //How humgry, thirsty, and happy the mover is, the higher it gets the more likely the mover is to seek water/food, and if it is high enough, the mover will die
  5.   float fear; //Various factors that affect the behavior of the mover
  6.   ArrayList standing;
  7.   int viewDistance; //Radius of detection for items such as food and water
  8.   boolean target; //Whetehr or not the mover is activley moving towards something
  9.   int speed,movementTimer,movementDir; //Speed relates to how fast the movement timer increases, and movementTimer/movementDir are used in Movement() to trigger a movement
  10.   Mover(float x, float y) { //Constructor
  11.     location = new PVector(x,y);
  12.     hungerLevel = 5;
  13.     thirstLevel = 0;
  14.     happinessLevel = 5;
  15.     standing = new ArrayList();
  16.     viewDistance = 5;
  17.     target = false;
  18.     speed = round(random(4,8)); //Randomises the speed for each mover
  19.   }
  20.   void Display() { //Shows the mover
  21.     if(happinessLevel<4) { //These conditionals change the color of the mover based on its happiness
  22.       stroke(255,0,0);
  23.     }
  24.     else if(happinessLevel>=4&&happinessLevel<=8) {
  25.       stroke(255,255,255);
  26.     }
  27.     else if(happinessLevel>8) {
  28.       stroke(0,255,0);
  29.     }
  30.     rectMode(CENTER);
  31.     rect(location.x,location.y,3,3); //Draws the point
  32.   }
  33.   void Update() { //Performs various changes in miscelanious values, including managing hunger, thirst, and happiness
  34.     movementTimer+=speed;
  35.     hungerLevel+=0.0005;
  36.     thirstLevel+=0.0012;
  37.     if(hungerLevel<2&&happinessLevel<10) {
  38.       happinessLevel+=0.006;
  39.     }
  40.     else if(hungerLevel>5&&happinessLevel>0) {
  41.       happinessLevel-=0.01;
  42.     }
  43.     if(thirstLevel<2&&happinessLevel<10) {
  44.       happinessLevel+=0.006;
  45.     }
  46.     else if(thirstLevel>5&&happinessLevel>0) {
  47.       happinessLevel-=0.012;
  48.     }
  49.   }
  50.   void Behavior() { //Behavior regarding targets, other movers etc
  51.     Iterator<Target> mTargets = tManager.targets.iterator();
  52.     while(mTargets.hasNext()) {
  53.       Target t = mTargets.next();
  54.       //if((sq(t.location.x-location.x))+(sq(t.location.y-location.y))<sq(viewDistance)) {
  55.         if(t.type=="Water"&&thirstLevel>5) {
  56.           targetLocation.x=t.location.x-location.x;
  57.           targetLocation.y=t.location.y-location.y;
  58.           target=true;
  59.         }
  60.         else if(t.type=="Food"&&hungerLevel>5) {
  61.           targetLocation.x=t.location.x-location.x;
  62.           targetLocation.y=t.location.y-location.y;
  63.           target=true;
  64.         }
  65.         else if(t.type=="Waypoint") {
  66.           targetLocation.x=t.location.x-location.x;
  67.           targetLocation.y=t.location.y-location.y;
  68.           target=true;
  69.         }
  70.         else {
  71.           target=false;
  72.         //}
  73.       }
  74.     }
  75.   }
  76.   boolean Alive() { //True/false for whether or not the mover is alive, if it is false the mover is removed
  77.     if(hungerLevel<10&&thirstLevel<10) { //Checks the hunger/thirst levels
  78.       return true;
  79.     }
  80.     else {
  81.       return false;
  82.     }
  83.   }
  84.   void Movement() { //Performs movements for the mover
  85.     if(movementTimer>50&&target==false) { //Counter for moving it every cerian ammount of time, and making sure it has no target, as this is for randomly moving
  86.       movementDir=floor(random(5)); //Randomises the direction
  87.       if(movementDir==0) { //Right
  88.         location.x++;
  89.         movementTimer=0;
  90.       }
  91.       else if(movementDir==1) { //Down
  92.         location.y++;
  93.         movementTimer=0;
  94.       }
  95.       else if(movementDir==2) { //Left
  96.         location.x--;
  97.         movementTimer=0;
  98.       }
  99.       else if(movementDir==3) { //Up
  100.         location.y--;
  101.         movementTimer=0;
  102.       }
  103.       else { //Mover is resting
  104.         movementTimer=-100;
  105.       }
  106.     }
  107.     else if(movementTimer>50&&target==true) {
  108.       targetLocation.normalize();
  109.       targetLocation.mult(1);
  110.       location.add(targetLocation);
  111.     }
  112.   }
  113.   void CheckEdges() { //Bounces the mover back if they try to wander off screen
  114.     if(location.x<0) {
  115.       location.x++;
  116.     }
  117.     else if(location.x>width) {
  118.       location.x--;
  119.     }
  120.     if(location.y<0) {
  121.       location.y++;
  122.     }
  123.     else if(location.y>height) {
  124.       location.y--;
  125.     }
  126.   }
  127.   void Emoticon() { //DIsplays an "emoticon" above the mover to show why it is happy/unhappy
  128.     float emoticonCycler=0;
  129.     if(thirstLevel>5&&emoticonCycler>0&&emoticonCycler<1) {
  130.       stroke(#0F79CE,150);
  131.       point(location.x,location.y-1);
  132.     }
  133.     if(hungerLevel>5/*&&emoticonCycler>1&&emoticonCycler<2*/) {
  134.       stroke(#0F79CE,150);
  135.       point(location.x,location.y-1);
  136.     }
  137.     emoticonCycler+=0.25;
  138.     if(emoticonCycler>5) {
  139.       emoticonCycler=0;
  140.     }
  141.   }
  142. }

Target class:

Copy code
  1. class Target {
  2.   PVector location;
  3.   float urgency;
  4.   String type;
  5.   boolean active;
  6.   Target() {
  7.   }
  8. }

TargetManager class:

Copy code
  1. import java.util.Iterator;
  2. class TargetManager {
  3.   ArrayList<Target> targets;
  4.   TargetManager() {
  5.     targets = new ArrayList<Target>();
  6.     targets.add(new MousePointer());
  7.   }
  8.   void Manage() {
  9.     Iterator<Target> mTargets = targets.iterator();
  10.     while(mTargets.hasNext()) {
  11.       Target t = mTargets.next();
  12.     }
  13.   }
  14. }

MousePointer class:

Copy code
  1. class MousePointer extends Target {
  2.   MousePointer() {
  3.     location = new PVector(mouseX,mouseY);
  4.     type = "Waypoint";
  5.   }
  6.   void Display() {
  7.     stroke(255);
  8.     line(mouseX,mouseY-5,mouseX,mouseY+5);
  9.     line(mouseX-5,mouseY,mouseX+5,mouseY);
  10.   }
  11.   void Update() {
  12.     location.x=mouseX;
  13.     location.y=mouseY;
  14.   }
  15. }
Quick edit: Based on the location of the null error, my Mover seems to recognize that there is a target available. Also, I commented out the leftover MousePointer things in the main sketch from before I made MousePointer an extension of Target.

Replies(8)

The NPE is caused by the fact that you declare targetLocation as one of the variables in the Mover class, but you do not initialize/assign it through your constructor or otherwise.

For example if you were to comment out the first line in your Mover constructor location = new PVector(x, y); then you would also get the same kind of NPE for the location variable.

Thanks! That fixes the null error. I ran into another error though... It seems that by having MousePointer extending Target, the ArrayList of Targets doesn't recognize the class. Here is some code I changed to try to fix it, (Removing the <Target>s and replacing Target t with Object t) but it still doesn't work.
Code:

MousePointer class:

Copy code
  1. class MousePointer extends Target {
  2.   MousePointer() {
  3.     location = new PVector(mouseX,mouseY);
  4.     type = "Waypoint";
  5.   }
  6.   
  7.   void TargetManage() {
  8.     location.x=mouseX;
  9.     location.y=mouseY;
  10.     stroke(1);
  11.     line(location.x-5,location.y,location.x+5,location.y);
  12.     line(location.x,location.y-5,location.x,location.y+5);
  13.   }
  14. }

Target class:

Copy code
  1. class Target MousePointer {
  2.   PVector location;
  3.   float urgency;
  4.   String type;
  5.   boolean active;
  6.   Target() {
  7.   }
  8. }

TargetManager class:

Copy code
  1. import java.util.Iterator;
  2. class TargetManager {
  3.   ArrayList targets;
  4.   TargetManager() {
  5.     targets = new ArrayList();
  6.     targets.add(new MousePointer());
  7.   }
  8.   void Manage() {
  9.     Iterator mTargets = targets.iterator();
  10.     while(mTargets.hasNext()) {
  11.       Object t = mTargets.next();
  12.       t.TargetManage();
  13.     }
  14.   }
  15. }


Don't get frustrated.....

You are using objects which belong to object oriented programming.
see
http://www.processing.org/learning/objects/
very convenient !

You are also using arraylists, which are some kind of an array.
a simple example:

Copy code
  1. //
  2. //Arraylist simple
  3. ArrayList<String> s = new ArrayList();
  4. size (400, 400);
  5. s.add("a"+str('b'));
  6. s.add("Hello");
  7. s.add("there!");
  8. for (int j = 0; j< s.size(); j++) {
  9.   String myText = s.get(j);
  10.   // font = loadFont("YuppyTC-Regular-40.vlw");
  11.   //textFont(font);
  12.   textSize(20);
  13.   fill(200, 255, 255);
  14.   text(myText, 20*j+33, 39*j+39);
  15. } // for

you can see,
  • ArrayList is created, elements are added and displayed.

or look at this

Copy code
  1. /**
  2.  * ArrayList of objects
  3.  * by Daniel Shiffman. 
  4.  *
  5.  * This example demonstrates how to use a Java ArrayList to store
  6.  * a variable number of objects.  Items can be added and removed
  7.  * from the ArrayList.
  8.  *
  9.  * Click the mouse to add bouncing balls.
  10.  */

  11. ArrayList balls;
  12. int ballWidth = 48;

  13. void setup() {
  14.   size(640, 360);
  15.   noStroke();
  16.   // Create an empty ArrayList
  17.   balls = new ArrayList();
  18.   // Start by adding one element
  19.   balls.add(new Ball(width/2, 0, ballWidth));
  20. }

  21. void draw() {
  22.   background(255);
  23.   // With an array, we say balls.length, with an ArrayList, we say balls.size()
  24.   // The length of an ArrayList is dynamic
  25.   // Notice how we are looping through the ArrayList backwards
  26.   // This is because we are deleting elements from the list 
  27.   for (int i = balls.size()-1; i >= 0; i--) {
  28.     // An ArrayList doesn't know what it is storing so we have to cast the object coming out
  29.     Ball ball = (Ball) balls.get(i);
  30.     ball.move();
  31.     ball.display();
  32.     if (ball.finished()) {
  33.       // Items can be deleted with remove()
  34.       balls.remove(i);
  35.     }
  36.   }
  37. }

  38. void mousePressed() {
  39.   // A new ball object is added to the ArrayList (by default to the end)
  40.   balls.add(new Ball(mouseX, mouseY, ballWidth));
  41. }


You can also have an arrayList of objects.

With that it's the same:
  • ArrayList is created, objects are invoked and as elements added and then displayed.

Greetings, Chrisir    




... It seems that by having MousePointer extending Target, the ArrayList of Targets doesn't recognize the class.
Taking a quick look at your code I've found this:
Copy code
  1. class TargetManager {
  2.   ArrayList<Target> targets;

  3.   TargetManager() {
  4.     targets = new ArrayList<Target>();
  5.     targets.add(new MousePointer());
  6.   }
You declare field targets as an ArrayList to store instances of class Target.
However, you add() instances of MousePointer into it instead!

Even though class MousePointer extends Target, it's like a one-way inheritance from parents to their children.
Lemme explain it better:

MousePointer has everything Target has, plus whatever is included later.
But class Target has nothing from MousePointer. A parent class doesn't get any of their children's!
You can say a children class is more powerful and fatter than its previous parent!  

So, what this explanation has anything to do w/ my ArrayList< Target>?

Since targets was supposed to store instances of Target,
it can't access anything exclusive from MousePointer!  
Unless you force a (cast) operator before trying to get anything from there.

In short, normally, targets can only access fields + methods from class Target alone,
but not from any of its children w/o some (cast)!

Possible solutions:

You can declare targets to store type MousePointer:
List < MousePointer > targets = new ArrayList();   // or...

Declare a subsidiary/derivative variable from it:
List<Target> targets = new ArrayList();
List<MousePointer> targetsMouse = (List<MousePointer>) targets;  // <--- untested!  *_*

Thanks! I tried it without the <Target> part for defining the ArrayList, and replaced Target t (In the iterator part) with Object t right after I posted this, but it still didn't work. Would there be any way to get both inside the same ArrayList so I can have the mover only check 1 ArrayList? (Would make it simpler, especially once I continue with this sketch.)

Would there be any way to get both inside the same ArrayList
so I can have the mover only check 1 ArrayList?
By "both" you mean instances of class Target & class MousePointer in the same ArrayList targets???

When using a List or any other Collection structure, you can store any mix of any types inside it.
Problem arises when you try to retrieve an element from such a mess mix!
You have to guess a valid (cast) operator for each item from such a List!

Let's say you have an ArrayList w/ 3 different types in there!
Every time you read an element, you have to try each of the 3 possible (cast) types!  

I don't see you using -> targets.add( new Target() );
You only add -> targets.add( new MousePointer() );

So, why do you need targets to be of type List< Target>???
Isn't List< MousePointer> enough?  

Or do you intend on using instances of parent class Target later?
If so, it's better to have another variable to store its instances, apart from MousePointer's.

Or even have a 2nd variable pointing to the same ArrayList, but w/ Target quality,
as the 2nd fix example I've given you from previous post!

I intended to have MousePointer be sharing the ArrayList with other Targets, I just had MousePointer there first for testing if I did it right. I asked my teacher about it, and he gave me a book about Processing, and I read the chapters about ArrayLists (Most of which I already learned) and Inheritance (Extensions and polymorphism, which proved invaluable) so I think I can solve most of those problems now. Thanks for helping though! 

I intended to have MousePointer be sharing the ArrayList with other Targets...
By "other Target" I believe you meant other child classes which extends Target as MousePointer did, right?

I haven't said you couldn't have 1 ArrayList to store all of them together.
It's just that it makes retrieving the different types of data objects harder.

Anyways, I believe you're gonna need to use operator instanceof for such endeavour. Good luck! 
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op2.html