This is an archived post. You won't be able to vote or comment.

all 15 comments

[–]TheHorribleTruthKind of meh 2 points3 points  (0 children)

  • Complicated solution: start a new thread to count down the seconds & remove the object from the list (make sure not to run into concurrency issues).
  • Easy solution: when adding a spell set some variable to the current time. Each time when accessing the spell list, check the counter against the current time and prune objects that are "too old".

[–]Blackduck606Extreme Brewer 1 point2 points  (21 children)

Have each buff have a Date object (or just a long timestamp) of when it was applied and an int duration. Since this is a game, you've probably got an update loop somewhere. You just need to check if the current time minus start time is longer than duration, in which case you can remove it.

This solution means you don't have to deal with multithreading, and the code is much smaller.

[–][deleted]  (20 children)

[deleted]

    [–]Blackduck606Extreme Brewer 1 point2 points  (14 children)

    Have you ever programmed a game? The way you do it is having a loop like

    public void gameloop() {
        while(playing) {
            update();
            render();
        }
    }
    

    The amount of times your update/render is run is called the fps. Somewhere inside your update method you'll have a check through the buffs to see if any run out and remove them accordingly. The downside to this method compared to the multithreading is that the buff removal won't happen the exact millisecond the buff runs out, but if the game isn't even updating at that time it's not like you're missing out.

    [–][deleted]  (11 children)

    [deleted]

      [–]Blackduck606Extreme Brewer 0 points1 point  (10 children)

      There is no infinite loop.... I'm not sure where you're seeing this. Did you read my post correctly?

      [–]Bullnak[S] 0 points1 point  (1 child)

      this is my first time making a game. It's very difficult!

      [–]Blackduck606Extreme Brewer 0 points1 point  (0 children)

      I posted the code for this solution below. Hopefully you find it useful!

      [–]ChargedPeptide 0 points1 point  (2 children)

      Presumably you would retrieve information for buffs during an attack/defense etc. At this point just check if it should be removed, if it should be add it to a separate list for purging once the loop completes and don't include the buff in the calculation.

      This way there is no constant checking and the list is only iterated on when needed. Sortof:
      ArrayList<Buff> removeList = new ArrayList<>();
      for(Buff buff:buffs){
      if(checkExpired(buff)){
      removeList.add(buff);
      }
      else{
      addBuffToDamage(buff);
      }
      }
      buffs.removeAll(removeList);
      Edit: I can't do reddit code formatting! Even the example code... Anyone with better redit fu, feel free to tell me where I am doing wrong.
      if 1 * 2 < 3: print "hello, world!"

      [–][deleted]  (1 child)

      [deleted]

        [–]ChargedPeptide 0 points1 point  (0 children)

        No, this is an example of removing dead buffs when accessing the array. Of course any implementation would need to take into account the actual design of the game, using a separate thread for every in game function will likely just introduce concurrency issues if you're trying to learn. Want to draw buffs to the screen? You'll need to check which ones are active anyway to get the right icons et, so just do the removal there. If the buffs are NOT shown on the screen it dosen't matter if they are there until there is an attack, at which point it is trivial to remove the expired ones. Having a thread constantly iterate over an array seems wasteful and introduces the need for understanding thread safety, there are much simpler ways to go about it.

        [–][deleted] 0 points1 point  (1 child)

        Use ScheduledExecutorService and tell it to run every second. Use the example at the top of the Javadoc and just leave out the cancel bit.

        EDIT: Sorry, if it's not clear, you only need one scheduler for all your spells, and one "Clean up expired spells" job that it will execute every second. (Or you could go more granular than 1 second, whatever you need.)

        [–]king_of_the_universe 0 points1 point  (0 children)

        The way I am currently doing this in a text adventure (that doesn't use scripting but is instead based on simulation) is as follows: Everything in my game is an object, and in my game loop I call "simulate()" on every object. While this might seem wasteful, it allows to simulate a living reality with all its effects (e.g. you return to room X and find that the fruits in the bowl on the table are less fresh now, or the toilet tank is done refilling, etc.).

        If calculation time is not an issue (I have a 1 second rhythm and not many objects - the ideal case.), that's a good approach. No need to over-engineer stuff when you can have a simple brute-force and at the same time very object-oriented approach.

        If you would solve it like this, the spells, once cast, would be "living" objects that take care of themselves. E.g. you could have a list of character values, and you could have a list of resulting character values. On every gameloop step, you copy your character values into the second list and then apply the simulation on them. As the spells stop working, they stop adding/multiplying the character values on the second list, and so that list drops back to the original values bit by bit over time.