Inheritance in a class with an array loop

edited December 2015 in Questions about Code

Hey,

I have a pretty massive class (well it's big for me!) that includes a collision detecting function. It's a class for objects like apples that fall down and when they hit the apple cart they disappear and add a point, or they hit the ground and just disappear.

I want to add two similar kinds of dropping items that also use the same collision points and also grant/detract points (this is why I use the 'points' int instead of just doing score++ for example). I'm confused how I can let something inherit this when I based my loops on the arraylist for this specific type of thing. Is it possible to use the @Override function somehow to replace it without having to basically copy/paste it all twice?

I have tried replacing the applelist.get(i).x part with x (and same for y), but then all the apples onscreen would be deleted instead of the specific apple.

This is the section of code that I want another class to inherit.

void objcollision() {
  // boolean stuff
  for (int i = applelist.size() - 1; i >= 0; i--) { // continuous loop
    distX = pstartX - applelist.get(i).x;
    distY = pstartY - applelist.get(i).y;

    // boolean collision detection
    if (distX > -55 && distX < 0
      && distY > -10 && distY < 6) { 
      distbool = true; // in range, true
    } else { 
      distbool = false; // not in range, false
    }
  }

Answers

  • It's a while since I experimented with inheritance in Processing/Java; so not sure how up-to-date I am on this topic. Anyway - an abstract class might be a good place to start with this: you first define core properties that all your similar objects will share and then extend from this.

    I've got a long forgotten demo on openprocessing that contains an example of inheriting from an abstract class (won't work in Processing 3 or possibly 2; but demonstrates the principles). In this case Ball extends the abstract class Body. Notice how Body sets properties that all children might have like x,y,vx,vy etc. and also contains methods that all children might need: move(), boundsWrap(), boundsBounce()

    Also notice that when you know a method will need to be called from another method in the abstract class - as is the case with checkBounds() in move() - but the implementation is left to its children, you should define an empty placeholder method in the abstract class:

    abstract void checkBounds();

    IIRC without this the code won't compile and of course child classes can override parent properties/methods...

    From your description this approach should be applicable to your class.

  • edited November 2015 Answer ✓

    BtW, I've got a very old rudimentary online game example about a bucket catching raindrops:
    http://studio.ProcessingTogether.com/sp/pad/export/ro.9mzpXAdqbigsO

    Anyways, as @blindfish said, traditional OOP inheritance fits like a glove for your case here.

    The trick is establishing some abstract class or interface which describes the general properties all your sprites/entities/actors got in common.

    Let's call it Actor. It got coordinates x & y, dimensions w & h, and fill color c.

    Also let's establish a contract that all Actor subclasses gotta implement methods update() & display().
    Joining everything together we got something like this: ;;)

    // forum.Processing.org/two/discussion/13616/
    // inheritance-in-a-class-with-an-array-loop
    
    // GoToLoop 2015-Nov-23
    
    abstract class Actor {
      float x, y;
      int w, h;
      color c;
    
      Actor(float _x, float _y, int _w, int _h, color _c) {
        x = _x;
        y = _y;
        w = _w;
        h = _h;
        c = _c;
      }
    
      abstract void update();
      abstract void display();
    }
    

    Now let's try out to be more specific and split Actor class into 2 more classes.

    Dropper represents every Actor that drops towards the ground and got extra method hitGround()
    Plus fields missed & sy representing respectively how many hit the ground and its vertical speed:

    abstract class Dropper extends Actor {
      int missed;
      float sy;
    
      Dropper(float x, float y, int w, int h, color c, float vy) {
        super(x, y, w, h, c);
        sy = vy;
      }
    
      abstract boolean hitGround();
    }
    

    And finally another abstraction to represent each Actor that tries to catch Dropper objects.
    This time its extra method is gotDropper() and fields caught & sx:

    abstract class Catcher extends Actor {
      int caught;
      float sx;
    
      Catcher(float x, float y, int w, int h, color c, float vx) {
        super(x, y, w, h, c);
        sx = vx;
      }
    
      abstract boolean gotDropper(Dropper d);
    }
    
  • edited December 2015 Answer ✓

    Finally we got our 1st non-abstract class: Apple. Which extends Dropper.
    In order to inherit from all those abstract methods, it is now obliged to finally implement them all.

    Therefore Apple gotta implement update(), display() & hitGround().
    Below just some template of it so you got an idea how to finish it:

    class Apple extends Dropper {
      Apple(float x, float y, int w, int h, color c, float sy) {
        super(x, y, w, h, c, sy);
      }
    
      @ Override void update() {
        // Implementation below:
      }
    
      @ Override void display() {
        // Implementation below:
      }
    
      @ Override boolean hitGround() {
        return y+h > height;
      }
    }
    

    Now the same pattern for class Cart which extends Catcher:

    class Cart extends Catcher {
      Cart(float x, float y, int w, int h, color c, float sx) {
        super(x, y, w, h, c, sx);
      }
    
      @ Override void update() {
        // Implementation below:
      }
    
      @ Override void display() {
        // Implementation below:
      }
    
      @ Override boolean gotDropper(Dropper d) {
        return x+w > d.x & x < d.x+d.w/2 & y+h > d.y & y < d.y+d.h/2;
      }
    }
    
  • Thanks for the help, I'll have to try it next week once my other project is done :)

  • edited December 2015

    Hello again!

    Thank you very much blindfish and GoToLoop. I made it work, although I eventually didn't use an abstract class anymore as I created two functions within the dropper class that all of them could use. It works perfectly, thank you :)

    I just changed a few things like:

     Actor(float _x, float _y, int _w, int _h, color _c) {
        x = _x;
        y = _y;
        w = _w;
        h = _h;
        c = _c;
      }
    

    here I just used this.x = x etc :)

  • edited July 2016

    If I understand well the system :

    Herbivore cow_1 = new Cow(10, 3) ;
    Cow cow_2 = new Cow(15, 1) ;
    Zebu zebu = new Zebu(15,3, "Madagascar") ;
    void setup() {
      println(cow_1.get_size()) ;
      println(cow_2.get_size()) ;
      zebu.eat_grass() ;
    }
    
    interface Agent {
      int get_size() ;
    }
    
    abstract class Mammal implements Agent    {
      int size ;
      Mammal(int size) {
        this.size = size ;
      }
    }
    
    abstract class Herbivore extends Mammal {
      int grass_type ;
      Herbivore(int size, int grass_type) {
        super(size) ;
        this.grass_type = grass_type ;
      }
    
      void eat_grass() {
      }
    }
    
    class Cow extends Herbivore   {
      Cow(int size, int grass_type) {
        super(size, grass_type) ;
      }
    
      int get_size() {
        return size ;
      }
    }
    
    
    class Zebu extends Cow {
      String country ;
      Zebu(int size, int grass_type, String country) {
        super(size, grass_type) ;
        this.country = country ;
      }
    
      int get_size() {
        return size ;
      }
    }
    
Sign In or Register to comment.