3

I'm making a game. I create an array that holds all my shapes. I need to move the shapes every 0.1 second or something small. At the same time I also have a circle following my mouse. I need to be able to move the circle following my mouse all the time but I haven't found a way to move the other circles a little bit each second. When I tried to move the other circles they would all move instantly before the javaFX window even loaded.

This is my Array

I create a circle and add it to my shape array

ArrayList<Shape> Objects = new ArrayList<Shape>();

Circle I = ClassObjects.getCircle(randomWidth,randomX,randomY);    
Objects.add(I);

Ive tried to use

final ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
    executorService.scheduleAtFixedRate(Timingobjects::myTask, 0, 1, TimeUnit.SECONDS);
}//                                program name, function, wait before start, time before each loop

    private static void myTask() {

        System.out.println("Running");
    }

But I found that this is a runnable executor service so no return value can be passed out and I also can't get the array to be passed in.

Ive tried to look at callable executor service but I can't understand how to code it.

If someone could give me an example of an executable that run every 0.1 seconds and can have my shape array list passed into it so it can be altered and then returned back out.

I would be very grateful.

Sergei Rybalkin
  • 3,337
  • 1
  • 14
  • 27
Dynermite
  • 189
  • 2
  • 13
  • 2
    You should be creating a JavaFX animation to do this. You can't directly modify UI elements from threads other than the UI thread, and trying to schedule tasks for animation has too much overhead and not enough determinism to run smoothly. – erickson Jan 10 '17 at 15:54

2 Answers2

1

See the use of Timeline in the Oracle Animation and Visual Effects in JavaFX tutorial for an example.

Otherwise you can use an AnimationTimer.

You don't need to pass an array to the Timeline or AnimationTimer as the nodes will be stored in the scene graph and you can just manipulate the scene graph nodes directly from within your Timeline or AnimationTimer event handling code.

For instance to create a Timeline which processes every 0.1 seconds:

final Timeline timeline = new Timeline();
timeline.setCycleCount(Animation.INDEFINITE);
timeline.getKeyFrames().add(
   new KeyFrame(Duration.millis(100)),
   new KeyValue(node.translateXProperty(), 25))
);
timeline.play();

Note that frame rates in JavaFX are processed at 60 frames per second by default. So the .1 second timeline won't be called exactly each .1 second.

Also related:

Community
  • 1
  • 1
jewelsea
  • 150,031
  • 14
  • 366
  • 406
  • Not the answer but i am being stupid i should be using transitions to move my circles instead i was trying to change the x and y directly by changing the circles in the array. Thank you anyway since this is what sparked me to look in to javaFX more. – Dynermite Jan 10 '17 at 21:16
0

It is possible with TimerTask. Extend TimerTask like:

class CustomTimerTask extends TimerTask  {
    List<Shape> shapes;

    public CustomTimerTask(List<Shape> shapes, /* observers*/) {
       this.shapes = shapes;
    }

    @Override
    public void run() {
       // update shapes
       // notify( about mouse events or whatever)
    }
}

Do not try to return any value. Use observer pattern to notify subscribers.

And now

Timer timer = new Timer(true);
timer.scheduleAtFixedRate(new CustomTimerTask(shapes/*, */), 0, 0.1 * 1000);
Sergei Rybalkin
  • 3,337
  • 1
  • 14
  • 27