leaderboard for javafx game - java

Hello stackoverflow community! I am learning to program and am working on a "duck hunt" style javafx game for mobile devices where 3 types of ducks move horizontally across the screen. Each time a certain type of duck is clicked, that type of duck gets a point next to its name.
What I would like to do is display a global leaderboard after the game so you can see which type of duck was clicked the most out of everyone who has played the game. What is everyones preferred way of implementing something like this? If you have any questions please feel free to ask me. Thanks, -H.J.
Edit (4/20/16 1:40PM PST): Because my original post was put on hold because it was deemed to vague, I wrote up a very basic example program to help explain what I am trying to do. On my menu scene I would like to retrieve the total number of clicks on the red and green rectangles for everyone who has played this game worldwide, which is currently globalScoreRed and globalScoreGreen and set to 0 because this is one of the parts I need help with.
On the playGame scene, when you hit the GG button, I would like scoreRed and scoreGreen to be submitted to the leaderboard which would adjust the values when viewed from the menu screen.
This is a very bad game and I can attest is not a game I would enjoy playing, but I am trying to learn the concepts of how to send the values and retrieve them. Once again thanks for viewing my post and helping out, you are very much appreciated.
package LeaderboardHelp;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;
import javafx.stage.Stage;
public class LeaderboardHelpMain extends Application {
Stage window;
Scene menu, playGame;
private Rectangle targetRed = new Rectangle(40, 40);
private Rectangle targetGreen = new Rectangle(40, 40);
private int scoreRed = 0;
private int scoreGreen = 0;
private Text redScoreText = new Text("Red: " + scoreRed);
private Text greenScoreText = new Text("Green: " + scoreGreen);
private int globalScoreRed = 0;
private int globalScoreGreen = 0;
private Text globalRedScoreText = new Text("Worldwide Red Clicks: " + globalScoreRed);
private Text globalGreenScoreText = new Text("Worldwide Green Clicks: " + globalScoreGreen);
private boolean playable = false;
public static void main(String[] args) { launch(args); }
#Override
public void start(Stage primaryStage) throws Exception {
window = primaryStage;
Button startButton = new Button("Start!");
startButton.setOnAction(e -> window.setScene(playGame));
//menu scene layout
VBox menuLayout = new VBox(20);
menuLayout.getChildren().addAll(globalGreenScoreText, globalRedScoreText, startButton);
menu = new Scene(menuLayout, 600, 600);
Button ggButton = new Button("GG");
ggButton.setOnAction(e -> window.setScene(menu));
targetRed.setFill(Color.RED);
targetRed.setOnMouseClicked(event -> {
scoreRed += 1;
redScoreText.setText("Red: " + scoreRed);
});
targetGreen.setFill(Color.GREEN);
targetGreen.setOnMouseClicked(event -> {
scoreGreen += 1;
greenScoreText.setText("Green: " + scoreGreen);
});
targetRed.setTranslateX(50);
targetRed.setTranslateY(50);
targetGreen.setTranslateX(100);
targetGreen.setTranslateY(50);
greenScoreText.setTranslateX(500);
greenScoreText.setTranslateY(50);
redScoreText.setTranslateX(500);
redScoreText.setTranslateY(70);
ggButton.setTranslateX(250);
ggButton.setTranslateY(250);
//game layout
Pane gameLayout = new Pane();
gameLayout.getChildren().addAll(targetRed, targetGreen, redScoreText, greenScoreText, ggButton);
playGame = new Scene(gameLayout, 600, 600);
window.setScene(menu);
window.setTitle("Leaderboard Helper");
window.show();
}
}
Edit (4/20/16 8:45PM PST) So after more reading I came across oracles EchoServer example which is getting me on a track (not sure if its right or wrong track). I was thinking about having the server save the submitted scores in a text file. When the menu scene is called by client it will connect to the server and request the scores. The server will read the text file and send scores to the application client. When the GG button is pressed, the score is sent to the server which reads the text file, adds the news score to old score and then overwrites the score text file. Is there a better way of doing this? I do want this to be scalable allowing lots of users to add their score at the same time.

A web service would be required. A simple one that takes maybe the type of duck and the number of times it was clicked.
POST /duck/{type}/{clicks}
The web-service would need to be secured using HTTPS or HMAC, or better yet both.
For HMAC the key would need to be hidden and obfuscated in your code. Security is always breakable, its about making the effort not worth it for such a small payout to any would-be hacker.
To do HMAC properly one should use a NONCE when creating the digest (aka signature). The NONCE should have a short expiration time. Many implementations use the timestamp as a NONCE, other implementations have the NONCE being provided by the web service. For simplicity I would go with the former. If the NONCE is older than 2 or 3 seconds, then reject the request.

Related

Controlling volume of different sound files independent from each other using sliders

I've been working on this project with a peer for comp sci class, and I can't figure out how to make SFX and music have their own independent volume controls. Both the music and the SFX both play just fine when they need to (hovering/clicking on buttons, menu music, etc), and I made sliders for both of them (music volume and SFX volume), but for some reason only music can be controlled. I have sat here for hours trying to figure out why it doesn't work. The FloatControl gain does update with the slider (I printed out it's value and it was working just fine, just not updating the actual volume of the sound effects). I also got rid of everything to do with the music by commenting out everything regarding it's slider controls, audio input stream, gain control, etc; it was as if SFX was the only audio related thing in the program, but it still didn't work. I don't understand why since the code is identical to the music's code (just that "music" is now "sound").
The below code is not meant to be functional on it's own since the actual code is 605 lines so far and that's too long to post on here. It does contain the core components, so if you want to set it up to work you have to make the JFrame and all the buttons, or have me post the full code and sound files.
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.sound.sampled.*;
import java.awt.event.*;
import javax.swing.border.Border;
import javax.swing.BorderFactory;
import java.io.*;
import java.io.File.*;
import java.io.IOException;
public class AudioTesting {
// Declare Global Objects
static final String[] SFXName = {"menuHover", "buttonEnter", "buttonLeave", "gameStart"};
static final String[] TrackName = {"Bossfight_Incomplete"};
static final String userName = System.getProperty("user.name");
static Clip sound;
static Clip music;
static JSlider musicVolumeSlider;
static JSlider soundVolumeSlider;
public static void main(String []args){
GameSetting();
}
public static void GameSetting(){
musicVolumeSlider = new JSlider(-45,6,6);
soundVolumeSlider = new JSlider(-45,6,6);
musicVolumeSlider.setMajorTickSpacing(5);
musicVolumeSlider.setMinorTickSpacing(1);
musicVolumeSlider.setPaintTicks(true);
//musicVolumeSlider.setPreferredSize(new Dimension(SLIDER_SIZE_X,SLIDER_SIZE_Y));
// musicVolumeSlider.setBackground(menuColor);
musicVolumeSlider.addChangeListener(new SliderListener());
soundVolumeSlider.setMajorTickSpacing(5);
soundVolumeSlider.setMinorTickSpacing(1);
soundVolumeSlider.setPaintTicks(true);
// soundVolumeSlider.setPreferredSize(new Dimension(SLIDER_SIZE_X,SLIDER_SIZE_Y));
// soundVolumeSlider.setBackground(menuColor);
soundVolumeSlider.addChangeListener(new SliderListener());
}
//manages the loading and playing of sfx
public static void SFXManager(int sfx){
try{
sound = AudioSystem.getClip();
File sfxFile = new File("C:\\Users\\" + userName + "\\Documents\\" + SFXName[sfx] + ".wav");
sound.open(AudioSystem.getAudioInputStream(sfxFile));
}catch (Exception ex){}
sound.flush();
sound.start();
}
// manages the loading and playing of music tracks
public static void MusicManager(int track){
try{
music = AudioSystem.getClip();
File musicFile = new File("C:\\Users\\" + userName + "\\Documents\\" + TrackName[track] + ".wav");
music.open(AudioSystem.getAudioInputStream(musicFile));
}catch (Exception ex){}
music.start();
music.loop(Clip.LOOP_CONTINUOUSLY);
}
static class SliderListener implements ChangeListener {
public void stateChanged(ChangeEvent e) throws IllegalArgumentException {
float currentMusicVolume = 0;
float currentSoundVolume = 0;
FloatControl musicGainControl = (FloatControl) music.getControl(FloatControl.Type.MASTER_GAIN);
FloatControl soundGainControl = (FloatControl) sound.getControl(FloatControl.Type.MASTER_GAIN);
//-------------------------------------------------------------PROBLEM AREA v v v
//For changing the volume of the music (this works just fine)
if (e.getSource() == musicVolumeSlider){
currentMusicVolume = musicVolumeSlider.getValue();
//if the slider is all the way at it's lowest, set the volume to -80 (i.e. mute)
if (currentMusicVolume == -45){
currentMusicVolume = -80;
}
musicGainControl.setValue(currentMusicVolume); // Reduce volume by slider value
}
//for changing the volume of the sfx
if (e.getSource() == soundVolumeSlider){
currentSoundVolume = soundVolumeSlider.getValue();
//if the slider is all the way at it's lowest, set the volume to -80 (i.e. mute)
if (currentSoundVolume == -45){
currentSoundVolume = -80;
}
soundGainControl.setValue(currentSoundVolume); // Reduce volume by slider value
}
}
}
//-------------------------------------------------------------PROBLEM AREA ^ ^ ^
// I didn't implement it in here, but here is where all the mouse and event listeners go for the different buttons
// If a button is hovered over or pressed, it plays a sound from the index that corresponds with that sound
// I.e. if you hover over a button, call SFXManager(0); which plays the first sound in the array (buttonHover.wav) etc.
}
I've found these float controls to be kind of hit-or-miss, in part because they depend on the local PC and its OS. It's often the case that only the master gain works, if you want to change volumes in real time. The master gain changes will affect ALL the playing sounds.
You could follow the suggestion from the last paragraphs of the Oracle sound tutorial on audio controls and write your own volume controls. To do so requires intercepting the audio input stream, compiling the bytes into PCM, multiplying the PCM by a volume factor, converting the PCM back to bytes, and finally, shipping the bytes out via a SourceDataLine.
This is basically the plan I followed when I wrote AudioCue. You are welcome to use that code base as an example for rolling your own, or to import and directly make use of the files within your project. I tried to follow the Clip API as closely as I could, while adding real time volume controls for each playing audio instance. One limitation is that it only works with wav files. But if you can work with that, feel free to use the library. I'm happy to answer any questions if you have any trouble setting it up.
I'm currently learning how to make the program available as a Maven resource. I'm not clear on how the Gradle instructions work--another contributor did that part. It is pretty easy to just copy the five files into your project and use them with just a little tinkering to the import/package lines.

JavaFX TextFlow - empty Text Node not displaying empty (stealing character from adjacent Text)

This is how the window looks
The issue here is that the center Text (blue) should be empty, but for some reason is not.
The window is just a very simple JavaFX Application. The start method looks like this:
public void start(Stage stage) {
Pane main = new Pane();
TextProgress copy = new TextProgress();
main.getChildren().add(copy);
Scene scene = new Scene(main, 300, 200);
stage.setTitle("Test");
stage.setScene(scene);
stage.show();
}
TextProgress is a custom class that is basically a TextFlow with three Text Nodes in it. The contents of the three Texts is: "Hello ", "" (empty), "World". The problem is, as you can see in the image, that the Text in the middle 'stole' a character from the one on the right.
Before showing the code of TextProgress, let me list a few things that I've found while playing around with this, as to make the code understandable.
This entire code is just to show the problem, the original application was basically something to display the progress of copying a text by hand. The left Text would contain all the words that were already typed, the center Text the current word to type, and the right Text the text yet to type.
Furthermore, the center Text was split once more into a Text for the typed and untyped characters for the current word. In this example the "Hello" would be an already typed word, the empty Text would be the typed characters of the current word, and "World" would be the untyped characters of the current word. (Since we are not typing anything in this example, the other Text was left out.)
The reason I did not leave out the "Hello" is that the issue only occurs when there is a Text in front of the center Text (doesn't matter if empty or not).
Another way to prevent the issue is wrapping the two Texts for the current word in another TextFlow. (Text, TextFlow[Text,Text], Text). While this seems to solve the issue, it causes a different one. While typing text, and thus changing the contents of the Texts, the word wrap of the line currently being typed changes from time to time, e.g. a long word gets pushed down into the next line while being typed, then goes back up on the next word again. Note that this happens even though the combined length of all Texts always stays the same. This might be related to the issue of this question?
The only difference between the different Texts is the color. Regarding the other issue mentioned above, does this explain the changing word wrap?
The issue only ever occurred on the first character of the current word. Once the center Text (blue) is not empty anymore, everything is as expected.
I made sure the empty Text is actually empty
I added some prints for the BoundingBox of the center Text before and after displaying the window, the width attribute here is 0 before, ~28 afterwards.
If the two Texts for the current word are wrapped in another TextFlow, the width attribute here changes from 0 to -1. Is there a way to set the width of the empty Text to -1 without the additional TextFlow?
(Not sure whether to include just the TextProgress class here, or the entire Application, since the entire class is small.)
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.stage.Stage;
public class Window extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage stage) {
Pane main = new Pane();
TextProgress copy = new TextProgress();
main.getChildren().add(copy);
Scene scene = new Scene(main, 300, 200);
stage.setTitle("Test");
stage.setScene(scene);
stage.show();
}
private static class TextProgress extends TextFlow {
private Text typed;
private TextFlow current;
private Text currentTyped;
private Text currentUntyped;
public TextProgress()
{
double size = 30;
boolean wrap = false;
typed = new Text();
typed.setFont(Font.font(size));
typed.setFill(Color.ORANGERED);
typed.setText("Hello ");
currentTyped = new Text();
currentTyped.setFont(Font.font(size));
currentTyped.setFill(Color.DEEPSKYBLUE);
currentTyped.setText("");
printDelayed(1000);
currentUntyped = new Text();
currentUntyped.setFont(Font.font(size));
currentUntyped.setFill(Color.MEDIUMAQUAMARINE);
currentUntyped.setText("World");
if (wrap) {
current = new TextFlow();
current.getChildren().addAll(currentTyped, currentUntyped);
this.getChildren().addAll(typed, current);
} else {
this.getChildren().addAll(typed, currentTyped, currentUntyped);
}
}
private void printDelayed(long delay) {
System.out.println(currentTyped.getLayoutBounds());
new Thread(() -> {
try {
Thread.sleep(delay);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(currentTyped.getLayoutBounds());
}).start();
}
}
}
I appreciate any clues as to what is going on here. Again, the main question here is how to stop the center Text from displaying some character from the adjacent Text.
This is what i am guessing you are doing, which should work from the way my head is vibrating now :)
You have a TextFlow which has 3 Text (or Label) Nodes, respectively typed, untyped,currenttyped, all with the initial text " ".
Now when you type the key strokes are updated in the typed and currenttyped, and you conjure the next set of words and update it to untyped.
so it should work, because Textflow is just a horizontal,wrappable node of nodes, so if you have Labels or Text with different Paints all you have to do is update those respective nodes textProperty(), and i guess they will wrap on their own.
Hope it helped you Sir.

How to send key press input into a browser via code (e.g. java)

I plan on writing a solver to the recently popular 2048 game
github link
I'm wondering how I could go about this without actually building the game first then solving it... My question is: Is there a way I can send key presses (e.g. 'left' 'right' 'up' and 'down' ) into a web-browser via some sort of language like java/c?
Sorry if this question has been posted before, I was not sure how to actually phrase the question and could not find any results.
use keybd_event function to send key press,
example :
keybd_event(VK_UP,0xE0,0,0);//do click, it will be stay pressed until you release it
keybd_event(VK_UP,0xE0,KEYEVENTF_KEYUP,0);//release click
the second parameter is scan code,there is a list of make and break scan codes for each key
http://stanislavs.org/helppc/make_codes.html,
and here you can find the virtual key codes
http://msdn.microsoft.com/en-us/library/windows/desktop/dd375731(v=vs.85).aspx
Using Java applets you can add a text listener to your component and capture the Keystrokes. For example, in the code below you are capturing the keystrokes of a textbox.
import java.awt.event.*;
import java.awt.*;
import java.applet.*;
public class KeyReader extends Applet{
private static final long serialVersionUID = 1L;
public void init(){
TextField textBox = new TextField(" ");
add(textBox);
textBox.addKeyListener (new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int keyCode = e.getKeyCode();
System.out.println("You Pressed " + keyCode);
}
}
);
}
}

problems trying to separating gui from logic

GUI.java
package ccc;
import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
public class GUI implements ActionListener {
JFrame f;
JPanel bg, s, a;
JLabel ca, £, cav, co, cov, co2, pr, error;
JTextField tf;
JButton b1, b2;
public GUI(){
f = new JFrame();
bg = new JPanel();
bg.setSize(650, 500);
bg.setBackground(Color.darkGray);
bg.setLayout(null);
bg.setLocation(0, 0);
s = new JPanel();
s.setSize(180, 445);
s.setBackground(Color.white);
s.setLayout(null);
s.setLocation(10, 10);
a = new JPanel();
a.setSize(430, 445);
a.setBackground(Color.white);
a.setLayout(null);
a.setLocation(202, 10);
ca = new JLabel("CASH:");
ca.setSize(70,25);
ca.setLocation(10, 25);
£ = new JLabel("£");
£.setSize(10, 25);
£.setLocation(80, 25);
cav = new JLabel("128.23");
cav.setSize(80, 25);
cav.setLocation(90, 25);
co = new JLabel("COCAINE:");
co.setSize(70, 25);
co.setLocation(10, 50);
cov = new JLabel("6 units");
cov.setSize(70, 25);
cov.setLocation(80, 50);
co2 = new JLabel("COCAINE");
co2.setSize(70, 25);
co2.setLocation(10, 25);
pr = new JLabel("£39.95");
pr.setSize(60, 25);
pr.setLocation(90, 25);
tf = new JTextField();
tf.setSize(70, 25);
tf.setLocation(160, 25);
b1 = new JButton("BUY");
b1.setSize(70, 25);
b1.setLocation(270, 25);
b1.addActionListener(this);
b2 = new JButton("SELL");
b2.setSize(70, 25);
b2.setLocation(350, 25);
b2.addActionListener(this);
error = new JLabel();
error.setSize(200, 25);
error.setLocation(50, 50);
s.add(ca);
s.add(£);
s.add(cav);
s.add(co);
s.add(cov);
a.add(co2);
a.add(pr);
a.add(tf);
a.add(b1);
a.add(b2);
a.add(error);
bg.add(s);
bg.add(a);
f.add(bg);
f.setSize(650, 500);
f.setLayout(null);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
}
public static void main(String[] args) {
new GUI();
}
#Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == b1){
Buy a = new Buy();
a.Buy();
}
if (e.getSource() == b2){
}
}
}
Buy.java
package ccc;
public class Buy extends GUI {
String pri, qua, cas, uni, aaa;
double price, quantity, cash, units, total, deduction;
public Buy(){
pri = pr.getText();
price = Double.parseDouble(pri);
qua = tf.getText();
quantity = Double.parseDouble(qua);
cas = cav.getText();
cash = Double.parseDouble(cas);
uni = cov.getText();
units = Double.parseDouble(uni);
total = price * quantity;
if (cash >= total){
deduction = cash - total;
aaa = String.valueOf(deduction);
cav.setText(aaa);
}
else if (cash < total){
error.setText("Sorry, you don't currently have the funds");
}
}
}
Hi folks,
I am currently learning java and wanted to give myself a project that was both challenging and fun. I decided to build a game that I remember playing when I was a kid called dopewars.
This is my second attempt at this game. When I began my first attempt, all went well. After a short while my source code began to fill wildly out of control until I could continue no more as I kept getting lost within mountains of code.
I then decided to begin again, only this time I wanted to seperate the gui from the logic (2 different .java files). This is where my problem lies. Previously this would work fine. Since seperating my java files the functionality has stopped.
When I press jbutton b1, my program is supposed to take the price value of cocaine and the units value entered into the jtextfield by the user, perform a calculation by accessing a method within Buy.java, and then update the appropriate JLabels within the s jpanel of GUI.java.
For example, user x wants to buy cocaine at the price indicated, so he enters a value representing the quantity he would like. He then presses the buy button which ultimately deducts the money from his pocket which is shown on the left side of the program window by using a method within the Buy class.
I hope you can understand my explanation and I hope to hear from you soon. Thanks.in advance. My Source code is below.
Your problems begin right here:
public class Buy extends GUI {
Try to rewrite you game logic so that it does not know a single thing about GUI. Assume you want to make your game playable via command line. Your game logic should be written in a way that it does not have to be changed at all to make this possible.
Try to identify the interface through which the user interacts with model of the game. Then implement this interface.
Here are some ideas (I don't know DopeWars, so I'll give you some generalized examples)
public class MyGameEngine {
public PlayerData getPlayerData() { ... }
public void sellSomeStuff(int numberOfStuff) throws InvalidPlayerOperation {
if (numberOfStuff > getPlayerData().getAmountOfStuff() {
throw new InvalidPlayerOperation("Not enough stuff");
}
....
}
}
public class PlayerData {
public int getAmountOfStuff() { ... }
}
public class InvalidPlayerOperation extends RuntimeException { ... }
There are a lot of patterns in this area. But if you want really to learn something, try it without looking up patterns first. When you got it working, there will be enough time to learn about patterns and then you check your code if you used them intuitively or if you could introduce them to improve its quality.
In particular, the MVC pattern might be overkill for your simple game, especially if you don't want to use an MVC framework (you don't).
The Singleton pattern, on the other hand, seems simple at first but is generally bad style and will only cause problems later on.
The following answer in no shape or form encourages real dope wars ;)
MVC is your friend. The way I do this usually is to write the data and data manipulation parts of the code first, without any thought whatsoever as to how it's going to look on screen.
Try to separate out the "data" part of your code first. Keep that neatly elsewhere; simple pojo objects representing real world objects, for example.
Then write the operations you can do on those objects into different classes. Make these completely independent of UI, as I said before. This ensures that the functionality part of your code is nice and separate, and essentially test-able.
Then write your UI part. A button click routes to a method call in your operations part of the code, for example.
Hope that helps.

javafx animation looping

in c++ or c programming language, we know to change the cordinate we use gotoxy(x,y) and we can use looping and sleep to change the cordinate and making animation. like this;
for(x = 20; x < 25; x++){
gotoxy(x,20); cout << "*"
}
but my queston is how about in JAVAFX 2.0 programming? i'm using netbeans 7.2.
thanks for your any help.
Use the JavaFX Animation Package.
There are numerous examples in the JavaFX Animation Tutorial, as Andy pointed out in his comment.
And there is a cute example of a running horse animation loop.
The key is that you don't sleep the JavaFX application thread and you have to release control of the JavaFX thread back to the JavaFX system each time you update something and want it rendered. The JavaFX animation classes take care of these things for you so that you don't have to worry about it. If you just loop like you do in the sample code from your question, JavaFX will just render the scene once after your loop has completed and you will never see anything happen.
Here is a fairly boring example which uses a Timeline to emulate the c++ code in your question to move a dot a pixel every 400 milliseconds.
import java.util.Date;
import javafx.animation.*;
import javafx.application.Application;
import javafx.event.*;
import javafx.scene.*;
import javafx.scene.shape.Circle;
import javafx.stage.Stage;
import javafx.util.Duration;
/** Simple JavaFX Animation Sample. */
public class AnimationSample extends Application {
private int x = 20;
private String status = "";
private final Circle dot = new Circle(20, 20, 3);
private final TimeCounter counter = new TimeCounter();
public static void main(String[] args) throws Exception { launch(args); }
#Override public void start(final Stage stage) throws Exception {
final Timeline timeline = new Timeline(
new KeyFrame(Duration.ZERO, new EventHandler() {
#Override public void handle(Event event) {
refreshScene();
}
}),
new KeyFrame(Duration.millis(400))
);
timeline.setCycleCount(Timeline.INDEFINITE);
stage.setScene(new Scene(new Group(dot), 50, 50));
stage.show();
counter.reset();
timeline.play();
}
private void refreshScene() {
gotoxy(x, 20);
status = "*****".equals(status) ? "*" : status + "*";
System.out.println(String.format("%7d", counter.elapsed()) + " ms " + x + " " + status);
if (x == 24) {
x = 20;
} else {
x++;
}
}
private void gotoxy(int x, int y) {
dot.setCenterX(x);
dot.setCenterY(y);
}
class TimeCounter {
private long start = new Date().getTime();
void reset() { start = new Date().getTime(); }
long elapsed() { return new Date().getTime() - start; }
}
}
There are three different options in JavaFX, depending on your needs.
The most basic one is AnimationTimer. It's equivalent to Swing's Timer. It simply contains a handle method which is called on every frame, and passed current time as argument. You probably want some internal bookkeeping so that you do not do expensive calculations every time handle is called.
Transition has an interpolate(frac) method, which gets called with values of frac between 0.0 and 1.0. It's up to you to do all UI changes you want to, based on the frac value. Both Transition and Timeline extend Animation, so you can set stuff like cycle duration, whether the Transition is reversed at end, etc.
Timeline is the most complex one. You define arbitrary amount of KeyFrames (think of states) that contain wanted properties of different Nodes, and the Timeline will do all the work for you interpolating how to animate the change between the provided values. For example, you can give a keyframe where x property of a Node is 0, and another where it's 100, and Timeline will do the animating for you.
Have look at using a Timeline Animation. It is a key component of animation in JavaFX and
is used to establish when, and in what sequence, key parts of an animation occur.
Here is an example

Categories

Resources