0

I'm making my first game with libGDX and I'm currently working with the object collision methods. I have this code that works well, but is there a way to replace the foreach loops in a generic method? (I need to know if the object is a Solid, Rock, etc..)

MapLayers layers = map.getLayers();
MapLayer layer = layers.get(Game.BORDER_LAYER);
MapObjects objects = layer.getObjects();

//border
for(MapObject object : objects.getByType(RectangleMapObject.class)){
    Rectangle rect = ((RectangleMapObject) object).getRectangle();

    new Border(world, map, rect);
}

layer = layers.get(Game.SOLID_LAYER);
objects = layer.getObjects();

//solid bricks
for(MapObject object : objects.getByType(RectangleMapObject.class)){
    Rectangle rect = ((RectangleMapObject) object).getRectangle();

    new Solid(world, map, rect);
}

layer = layers.get(Game.TREE_LAYER);
objects = layer.getObjects();

//trees
for(MapObject object : objects.getByType(RectangleMapObject.class)){
    Rectangle rect = ((RectangleMapObject) object).getRectangle();

    new Tree(world, map, rect);
}

layer = layers.get(Game.ROCK_LAYER);
objects = layer.getObjects();

//rocks
for(MapObject object : objects.getByType(RectangleMapObject.class)){
    Rectangle rect = ((RectangleMapObject) object).getRectangle();

    new Rock(world, map, rect);
}

Edit: All objects inherit from the same abstract class

public class Rock extends InteractiveTileObject

And the Game.XXXX_LAYER is an integer that indicates the map layer in which those objects are located

Salek
  • 449
  • 1
  • 10
  • 19
iKurt
  • 1
  • 2
  • Code is all the same apart from the ctors. Just make a method that takes a _whatever `ROCK_LAYER` is_ and a custom _whatever those types are_ factory as an `@FunctionalInterface`. TBH I would rethink the whole design - those flagrant violations of the Law of Demeter are a significant code smell. – Boris the Spider Aug 18 '19 at 16:00
  • Thanks, I will try to do that. I'm new to this, sorry for the mess – iKurt Aug 18 '19 at 16:10

1 Answers1

-1

No, it will not be possible to do this with generics because you will not be able to instantiate an object by calling new T(world, map, rect). However, since there is a lot of repeated code in the 4 loops, you can make a separate method that takes the layer number and the Class representation of the object that needs creating. By using reflection, you can call the constructor of the class that is passed in order to instantiate your component.

public void createComponent(int layer, Class toCreate) {
    for(MapObject object : map.getLayers().get(layer).getObjects().getByType(RectangleMapObject.class)){
        Rectangle rect = ((RectangleMapObject) object).getRectangle();

        toCreate.getConstructor(World.class, Map.class, Rectangle.class).newInstance(world, map, rect);
    }
}

After making this method, you can call it as follows:

void main() {
    createComponent(Game.BORDER_LAYER, Border.class);
    createComponent(Game.SOLID_LAYER, Solid.class);
    createComponent(Game.TREE_LAYER, Tree.class);
    createComponent(Game.ROCK_LAYER, Rock.class);
}

You can also take a look at this thread to find out more about Reflection and its API's: What is reflection and why is it useful?

  • Why have you sovled something that could easily be solved with abstraction and good design, with reflection; which is not only not typesafe but also slow? – Boris the Spider Aug 18 '19 at 18:23