Search code examples
javaarraylistslick2d

How to call update method on one particular sprite from an ArrayList of Sprite objects created in Slick2D for a game?


I am using Slick2D to make a simple game with a number of sprites. There is a player sprite which will push other object sprites around the map.

I have used an ArrayList to store all the sprite types created, but when I use the player to push a particular type of sprite (for example a wooden block) all the occurrences of that particular sprite type in that map gets updated as well. How do I specify to update that one particular wooden block rather than updating all the wooden blocks loaded in the game?

ArrayList:

private ArrayList<Sprite> sprites;

Creating all the sprites and storing them inside the ArrayList:

public static ArrayList<Sprite> loadSprites(String filename) {

    ArrayList<Sprite> list = new ArrayList<>();

    /*bunch of code to load the sprite*/

    list.add(World.createSprite(name, x, y));

    return list;
}

here types is a 2D array where I am storing all the names of the sprites according to their map coordinates, which I am getting from a csv file.

public static Sprite createSprite(String name, float x, float y) {
    switch (name) {
        case "player":
            return new Player(x, y, "player");
        case "wood":
            return new Wall(x, y, "wood");
        case "tile":
            return new Floor(x, y, "tile");
        case "wall":
            return new Stone(x, y, "wall");
        case "metal":
            return new Target(x, y, "metal");
    }
    return null;
}

Thanks in advance. :)


Solution

  • What you need to do is to identify the object the player pushes. Let's assume you have three sprites in your list all of the type wood. From what you wrote in your question it seems like if the player starts pushing obviously all sprites get updated as well because either:

    • Your program can't determine what sprite exactly is supposed to be pushed.
    • Your program knows what sprite is supposed to be pushed but cant determine what sprite to update visually (hard to tell with your provided code)

    So what you should do is to ensure that the pushing action is only performed to the object/sprite the player is interacting with. You need to have constraints to check for this interaction this constraint might be pushing a button or intersecting with that one particular sprite / object. So you could do for example the following:

    1. Iterate through your arraylist and check with which object/sprite your player is intersecting.
    2. If there is an intersection with an object of your list you exactly know what object that is and you could call the update, push or any other method on the object.
    3. If you have more than one possible candidate to update you need to specify your search, for example you could only interact with objects / sprites your player is looking at.
    4. Call the needed method of that particular one object (eg. push()).

    What also might be a solution is that you should be sure about your game architecture. By this I mean that you should be certain about how your game is internally designed. Generally each gameobject in your game should have sprite and maybe a sound or certain other attributes. By this you make sure that each object has a specific sprite just for itself, so you wont get into trouble with updating any other sprites because you only can access this specific sprite by this specific object. So maybe you should consider not iterating over a list of sprites but rather iterate over a list of gameobjects in your world (I'm not sure but maybe a sprite is a gameobject for you, but a sprite is just the graphical representation of a gameobject.). Check for interaction with each of these gameobjects and in case perform a specific action. Such code could look like the following:

    //inside the update method of your player
    for(GameObject gameObject : world.getAllGameObjects()){             
                if(player.getHitbox().intersects(gameObject.hitbox())){
                    gameObject.update() //push, update sprite, whatever
        }
    }
    

    Checking for intersection is only one solution as I already said you could also check for the pressing of a key or for a certain distance. From my understanding what is important for you is the identification of a single object and to update that single object.

    It's hard to tell what exactly your problem is because I dont have insight in your entire code, but if you ensure to find the right object to interact with and also making sure that only this object is graphically updated this will work.

    Beside the architecture it self the problem might be here:

     if (Loader.getSpriteOfType("wood", Player.getPlayerX() - 1, Player.getPlayerY())) {
            dir = DIR_LEFT;
        }
    

    I'm not sure what Loader.getSpriteOfType(..) does since I don't know how sprites or objects are entirly stored and handled in your game cycle, but I'd assume that it returns all (not only a specific one) sprites of type "wood" because it's searching for "wood" and finds all objects which "wood", but you want only the exact one which your player is interacting with so maybe you should be more specific in that if-clause (just an assumption though since I don't know your code).

    Hope this helps you and gives you something to think about.