Animation! Done with TriggerAction

Can we have animation in Vassal?

Retrofit TriggerAction for thread-execution and animation.

class TriggerAction {
  boolean isBlocking = true;
  boolean isRestart = false;
  ThreadQueue threadQueue;
  Array keystrokesToPerform;

  public TriggerAction(boolean isBlocking) {
    this.isBlocking = isBlocking; this.isRestart = isRestart;
    threadQueue = new ThreadQueue(isBlocking, isRestart);
    threadQueue.start();
  }

  public void PerformKeystrokes() {
    threadQueue.addToQueue(new PerformThread());
  }

  class PerformThread extends Thread {
    public void run() {
      // Perform the keystrokesToPerform array;
    }
  }
}

class ThreadQueue extends Thread {
  boolean isBlocking = true;
  boolean isRestart = false;
  LinkedBlockingQueue queue = new LinkedBlockingQueue();
  Thread currentPerformThread;

  ThreadQueue(boolean isBlocking, boolean isRestart) {
    this.isBlocking = isBlocking; this.isRestart = isRestart;
  }

  public void run() {
    while (Vassal is running) {
      currentPerformThread = (Thread) queue.remove();
      thread.start();
      currentPerformThread.join();
    }
  }

  public void addToQueue(Thread t) {
    queue.offer(t, 60, TimeUnit.SECONDS); // catch interruptions, report error.
    if (isRestart) {
      currentPerformThread.interrupt();
    }
    if (isBlocking) {
      this.join(MAX_WAIT_TIME); // catch interruptions, report error.
    }
  }
}

In words…

TriggerAction will always run its “Perform keystrokes” code chunk in a separate thread (PerformThread).

A PerformThread will be added to a ThreadQueue.

By default, PerformThread will be blocking. CurrentThread will wait for it to finish.

For GUI…

Add a new checkbox to TriggerAction: “Non-blocking”.
When user ticks this checkbox:

[]Advise end-users:
[list]
[
]Race conditions might occur[/]
[
]Proper thread programming is required[/]
[
]Please limit execution time of thread (for performance considerations)[/*]

[/:m]
[
]Add new field “Queue or Restart?”.
Attempts to re-invoke the TriggerAction will either queue the attempt, or stop and restart the thread.
Restart thread is needed say when pressing “Escape” to cancel a long-running animation. Eg, “Cancel, I don’t want to make that move anymore”[/*]

[*]Further, when “Repeat this set of Keystrokes (Loop)?” is ticked:

[]Add new option to “Type of Loop”, namely “Repeat Forever”.[/]

[]Add a new field “Repetition Interval”, and limit this figure to 50ms and above. (Compulsory field! Default value to 60000ms.)
Prevent overly zealous repetitions with low “Repetition Interval” value. We want animation for a boardgame, not for a real-time first person shooter![/
]
[/*:m][/list:u]

Note that “Non-blocking” and “Repeat this set of Keystrokes (Loop)?” options are on the same level, neither are children of the other. They are inter-dependent, though.

Later on, when we have time, we can show the end-user where any particular TriggerAction is called from. Makes for easier thread programming.

Later later on, when we REALLY have time, we can show a flowchart of TriggerAction(s) and GlobalKeyCommand(s). Hmm. No, forget it. Bear in mind that proper thread programming is the onus of the programmer. We usually draw graphs and charts as documentation for our multi-threaded application. Vassal is NOT a thread programming IDE!