JavaFX wait for user input - java

I am writing a board game where I need to check for enemies on the the player is moving and prompt to make an attack. However because of how the game is made the move method is called on the JavaFX application thread, I want to be able to prompt the user if they want to fight an enemy.
My dialogue box which works fine normal uses wait and notify which dont work on the main thread without crashing the program, does anyone know how to pause the execution of this thread until a user clicks one of the buttons.
I apologise for the description, its late.
Method that checks for enemies
This method checks for the enemies and returns the enemy if the user selected yes. It runs on the JavaFX Thread.
private Ship pathBattle(Vector gridPosition){
//Check if there are ships on the path to the destination
for(Button cell : activeButtons){
//Check the button position is not that of the current button, dont go past the current button
Vector pixPosition = new Vector(cell.getLayoutX(), cell.getLayoutY());
//Convert to a grid referance
Vector gridPos = Vector.pixToGrid(pixPosition);
if(!gridPos.equals(gridPosition)){
//This button is not the destination
//Check for any ships on that cell
Ship collided = Ship.isOccupiedButton(cell);//Returns the ship if there is one on the cell
if(collided != null){
//There is a ship, prompt to battle
boolean battle = UtilPopups.showConfirmationDialog("Do you want to battle " + collided.getName(), "YAR!", "NAY!");
Game.printError("Ship collision");
if(battle){
return collided; //Return the ship to battle
}
}
}
//On to the next button
}
return null;
}
The code to display the Popup
This does work in other areas of the porgram with no issue
public static boolean showConfirmationDialog(String lblPrompt, String btnYes, String btnNo){
//Check if the confirmation controller is not null
if(confirmationDialog != null){
confirmationDialog.lbl_prompt.setText(lblPrompt);
confirmationDialog.btn_no.setText(btnNo);
confirmationDialog.btn_yes.setText(btnYes);
//Show the base
show(confirmationDialog.base_pane);
//Pause this thread until user input is given from GUI thread
synchronized (confirmationDialog) {
try{
confirmationDialog.wait();
} catch (Exception e) {
e.printStackTrace();
}
}
//Program resumed, user input given and stored in response
if(confirmationDialog.response.equals("yes")){
confirmationDialog.response = null; //Set back to null
return true;
} else {
confirmationDialog.response = null; //Set back to null
return false;
}
}
//Class not initialized
Game.printError("UtilPopups->showConfirmationDialog: Dialog NULL!");
return false;
}

For blocking any caller thread during showing dialog, for example:
static private void showAndBlock(Dialog dialog) {
if (Platform.isFxApplicationThread()) {
dialog.showAndWait();
} else {
CountDownLatch lock = new CountDownLatch(1);
Platform.runLater(() -> {
dialog.showAndWait();
lock.countDown();
});
try {
lock.await();
} catch (InterruptedException e) {
// Just in case you call yourTherad.interrupt(),
// the thread will be joined forcibly through here.
}
}
}
But I'm not sure whether or not it works in your threading design.

The collided method literally doesnt nothing, it doesn't ask for a input so it can't work.
I think, sorry not good english

Related

the read function in my socket API does not work and lags

I made a single mode chess game that is has no bugs as far as i know and i started the multiplayer mode.
After i connect the two players successfully, one window (the server player window) works but the opponent window lags the specific line "movement = opponentPlayer.in.readLine();", it shows no error or anything at all, in fact it stops the window from responding without showing any progress as shown here
Code:
private void receiveMovement() throws IOException {
System.out.println("I Entered receiveMovement");
String movement = null;
if (serverPlayer != null) {
System.out.println("I Entered serverPlayer");
movement = serverPlayer.in.readLine();
board.whiteTurn = movement.charAt(4) == 1;
} else if (opponentPlayer != null) {
System.out.println("I Entered opponentPlayer");
movement = opponentPlayer.in.readLine();
board.whiteTurn = movement.charAt(4) == 1;
}
System.out.println(movement);
// int yAxis1 = movement.charAt(0) -'a';
// int yAxis2 = movement.charAt(2) -'a';
// System.out.println(yAxis1);
// System.out.println(yAxis2);
// Coordinate sourceCoordinate = new Coordinate(movement.charAt(1), yAxis1); //not sure of the order
// Coordinate destinationCoordinate = new Coordinate(movement.charAt(3), yAxis2);
assert movement != null;
Coordinate sourceCoordinate = new Coordinate(movement.charAt(1), movement.charAt(0) - 'a');
Coordinate destinationCoordinate = new Coordinate(movement.charAt(3), movement.charAt(2) - 'a');
sourceTile = board.getTile(sourceCoordinate);
destinationTile = board.getTile(destinationCoordinate);
}
the system messages:
I Entered play Successfully
I Entered opponent play, i'm stuck
I Entered receiveMovement
I Entered opponentPlayer
Process finished with exit code -1
The read method in input streams is a blocking call (like explained in the api). Therefore your programm will always wait for input as soon as it reaches the readLine() method. If this method is called from a gui it will stop the gui and it freezes.
A solution would be to execute your code in another thread so the main thread doesn't get blocked. After receiving the data in the thread you can inform the gui or any other class that there is a new move (or any other data) available.

memory game java gui

I'm trying to write a logic in memory game that when I click on cards and they are not a pair (different ID), program should swap them back after 1s. If they are same, then leave them as they are.
The problem is that when I first click and the card appears, after second clicking on another (different) card it doesn't appear and swap the first card after 1s. someone knows why the second card does not appear after clicking?
Btw when the pair is correct, everything works fine, here is my fragment of the code responsible for that logic in listener:
final int copy = i;
card2.addActionListener((e) -> {
card2.setIcon(new ImageIcon(icons[copy].getAbsolutePath()));
if(firstClick == null)
{
firstClick = (Card)e.getSource();
}
else
{
Card secondClick = (Card)e.getSource();
if(firstClick.getID() != secondClick.getID())
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e1)
{
//e1.printStackTrace();
}
firstClick.setIcon(new ImageIcon(background.getAbsolutePath()));
secondClick.setIcon(new ImageIcon(background.getAbsolutePath()));
firstClick = null;
}
else
firstClick = null;
}
});
While method actionPerformed is executing, the GUI cannot react to mouse and keyboard events, so basically your code is "freezing" your GUI for one second. I believe that the class javax.swing.Timer is what you need and at first glance it looks like the duplicate question that MadProgrammer referred to may help you.

how to display the "Game over" image in android for a fixed amount of time and restart the game when user taps the screen after a specified interval?

I made clone of ""Flappy bird" game by watching video tutorials.i programmed it so that when the bird falls or collides with the tubes a game over message appears on the screen and the game restarts when the player taps on the screen.
The problem is that when the user fails to tap the bird in time and it collides with the tube,the game over screen appears immediately and the user happens to tap on the game over screen which results in restarting of the game.
This makes the user unable to see the score.I have already tried using Thread.sleep().Following is the code
(gameState == 2)
{
batch.draw(gameOver,Gdx.graphics.getWidth()/2-gameOver.getWidth()/2,Gdx.graphics.getHeight()/2-gameOver.getHeight()/2);
try
{
Thread.sleep(2000);
}
catch(InterruptedException ex)
{
Thread.currentThread().interrupt();
}
if (Gdx.input.justTouched()) {
gameState = 1;
startGame();
score =0;
scoringTube = 0;
velocity = 0;
}
}
With this code the problem is that even the gameover image is being delayed and the previous problem is still occuring but now with a delay.I basically need a way so that justTouched method becomes inactive for a while when the game over screen is there.Please help.
I really wouldn't recommend using Thread.sleep; instead, you could try to use a boolean that is changed once the game ended, and prevent the method from executing in that case. Combine that with e.g a Timer that resets it after a fixed delay, and you should have the solution to your problem.
Example Usage for the timer:
new java.util.Timer().schedule(
new java.util.TimerTask() {
#Override
public void run() {
//execute code here (change boolean state)
}
},
yourDelayHere
);

Don't see why this loop does not get reached

Because of many boolean checks i am a little confused, let me introduce me to my next code.
} else {
//check whether the player starts again. the first time we lose the player
//will definitely get into this loop
if(!startAgain){
// we only do this to set a timer, we don't want to start a new game so we set this
// to false
newgame = false;
startAgain = true;
deadTime = System.nanoTime();
}
deadTimepassed = (System.nanoTime() - deadTime)/1000000;
if((deadTimepassed < 2000) && (newgame = false)){
newGame();
}
}
}
This else statement can be seen as the first time a player gets hit by an enemy missile. To make an explosion-animation. I need te screen to freeze for 2 seconds and then start the game over again. I don't see why the second if statement is never reached. Here are my ontouch methods and my new game method:
#Override
public boolean onTouchEvent(MotionEvent event) {
//What happens when the player touches the screen!
if (event.getAction() == MotionEvent.ACTION_DOWN) {
// Boolean check for when player is playing, if he isn't the chopper does nothing.
// we see that the chopper only hangs still if all these booleans are true!
if ((!player.isPlaying()) && (newgame = true) && (startAgain = true)) {
player.setPlaying(true);
} if(player.isPlaying()) {
player.setUp(true);
startAgain = false;
}
return true;
}
if (event.getAction() == MotionEvent.ACTION_UP) {
player.setUp(false);
return true;
}
return super.onTouchEvent(event);
}
public void newGame(){
newgame = true;
missles.clear();
if(player.getScore()>best) {
best = player.getScore();
SharedPreferences.Editor editor = saveBest.edit();
editor.putInt("new best",best);
editor.commit();
}
player.resetScore();
player.setY(HEIGHT/2);
}
As one can see, the new game just resets the players position, the only thing i want to do is just freeze the screen for 2 seconds before that happens, this is supposed to happen in the second if statement but it never get reached...
Any suggestions?
ps: deadTimepassed is introduced as 'private long' just beneath the public class method.
For freeze your Thread (so, the program will be freeze, also your screen) during 2 seconds you can use Thread.sleep() function:
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
You have to put it inside a try-catch block because it can gives to you an InterruptedException.
I expect it will be helpful for you!

First mouse drag movement

Is there a way to figure out the first drag movement of the mouse in Java?
For example:
public void mouseDragged(MouseEvent e)
{
if (first drag of the mouse) // what should I write here?
System.out.println("This is the first drag");
else System.out.println("This isn't the first drag");
}
If I drag the mouse 5 times I should see this text in the console:
This is the first drag
This isn't the first drag
This isn't the first drag
This isn't the first drag
This isn't the first drag
boolean first=true;//this should be a instance variable.
first drag! use a boolean variable to detect first or not.like this
public void mouseDragged(MouseEvent e)
{
if (first) { // this is only true if it's first drag
System.out.println("This is the first drag");
first=false;
}
else {
System.out.println("This isn't the first drag");
}
}
update...
this is how u can detect is it first drag.but there are a problem normally mouse drag event triggered while dragging.to avoid this u can modify this little bit.
declare instance variables
boolean draging = true;
boolean mark = true;
boolean first = true;
print only when dragging start.when we print mouse dragging we stop printing it until mouse released and redragging.
public void mouseDragged(java.awt.event.MouseEvent evt) {
draging = true;
if (mark) {
if (first) {
System.out.println("This is the first drag");
}else{
System.out.println("This isn't the first drag");
}
mark = false;
}
}
change first to false so first dragging is enough.and ready for print new drag[mark = true]
public void mouseReleased(java.awt.event.MouseEvent evt) {
if (draging) {
mark = true;
first=false;
}
}
this is the output of 1st and updated examples.there is a problem of 1st code [because event drag is triggered continuously while dragging ,not ones].
first example
This is the first drag
This is the first drag
This is the first drag
.............................//this continues until u finish[released] first drag
This isn't the first drag
This isn't the first drag
This isn't the first drag
................................
updated one
This is the first drag //a drag [ click--move--relesed] mark only 1time
This isn't the first drag
This isn't the first drag
This isn't the first drag
...............................
I would modify FastSnails solution to this slightly to get around the behaviour that mouseDragged fires on every mouse movement while the button is down:
boolean first = true;
boolean triggered = false;
public void mouseDragged(MouseEvent e){
if(!triggered){
if(first){
System.out.println("This is the first drag");
first=false;
}
else{
System.out.println("This isn't the first drag");
}
triggered = true;
}
}
Of course, we then have to reset that flag in a mouseReleased event, which signals the end of the "drag":
public void mouseReleased(MouseEvent e){
triggered = false;
}
Using this method means that the message only gets triggered once per "drag", rather than at every mouse movement.

Categories

Resources