Wait for object to finish moving, then do action - java

I'm wondering if there is any built in way in Java to wait until something is finished, then keep going in the code.
In my case, I move an object from x to destinationX by 50px per frame when I press the object. To wait for that movement to finish before I keep going in my code I use a Timer atm, but I'm worried that might not be the best solution if someone runs on low fps.
Is there any way to do this without using a bunch of flags or a Timer? I looked into Events but can't find decent instructions on how I could apply it in my case.

You could work with states (= an integer) and change states once a condition is met, like
if(state == 1) moveObject();
if(state == 2) keepGoing();
and you change state from 1 to 2 once you reached the destination in moveObject();.

You can perform your actions in different threads and use Thread.join() as described here.

Related

Making Java game, found easy way to cheat, don't know how to prevent it

I'm making a game in Java, and I made it so that if you right click, the player teleports to the mouse to "escape". I want to make it so that you can only use it every 2 mins. and after trying and failing THAT, I found out that you can just hold down right mouse and the player will follow your mouse/clicker. I am using Processing 3.1.2 if that helps at all.
Every time you allow that player power to be used, note the current timestamp.
Next time the player attempts to activate that power, check the saved timestamp against the current time. If an insufficient number of seconds have passed, disallow the power.
If sufficient time has passed and you allow the power to activate, update the variable holding the time that the power was last used.
This is often called a "cool down" in games.
I would suggest using a javax.swing.timer. I have done this before, and within the mouseClicked event you set a boolean canTeleport = false. At the end of the javax.swing.timer, set canTeleport = true. The first thing that you can do when going inside mouseClicked,
if(canTeleport)
{
//teleport
}
//start timer

Better way to implement empty while loop to hold control

I am playing audio in background and I want the control of program to stay stand still till the audio playing is over for that I am using empty while loop as follows
while(isPlaying==true){};
mediaPlayer.stop();
as you can see while loop holds program control till audio is playing and after that next instruction is executed. This is working fine but I came to know that this is not a proper way to do this empty-while is expensive I am searching for alternative. Please Help.
Assuming your program is in Java (...why did you give it three language tags?) You have a few options. You could use a proper synchronization event, e.g.:
// fields
Object playerStopEvent = new Object();
boolean isPlaying;
// in your media player, when playback is complete:
synchronized (playerStopEvent) {
isPlaying = false;
playerStopEvent.notifyAll();
}
// elsewhere, when waiting for playback to complete:
synchronized (playerStopEvent) {
while (isPlaying) {
try {
playerStopEvent.wait();
} catch (InterruptedException x) {
// abort or ignore, up to you
}
}
}
mediaPlayer.stop();
See the official tutorial on Guarded Blocks for more examples.
You could also just have mediaPlayer call some callback when it is finished, and e.g. disable GUI components when you start playing and re-enable them when the finished callback is called (you could also use an event listener approach here).
Without more info, I recommend the latter, as it won't prevent you from doing other unrelated things (or keep your program from responding at all) while the player is playing, but the former may be more appropriate depending on your situation.
If it's in C or C++ the concept is the same. Use whatever equivalent of condition variables / events you have for the first option, or whatever equivalent of callbacks / listeners / signals+slots you have for the second.
well, in my humble opinion, it's better to use another implementation..
try to use thread so that it won't hang your program in there (it's a background audio afterall; you might want to do something else while the audio is playing)..
try to check this page out..
First thing is that you don't have to compare 2 Boolean fields that you have done in your code...
while(isPlaying==true){};
you can do so like..
while(isPlaying){};
and, now that you have told that you are using java, you can try this...
while(isPlaying){
Thread.sleep(1);
};
You may consider a sleep(time in milliseconds ). This will allow your thread executing while loop to sleep for specified milliseconds and then check the condition again.
while(isPlaying==true)
{
Thread.currentThread().sleep(1000); // sleep for 1 sec
};
This once is quick but the better way is to use some wait() and notify() mechanism as suggested by #JasonC in his answer.
You really don't need the {} in your empty while loop.
while(isPlaying); would suffice.
Also, as others have already suggested, consider using a delay inside your loop, i.e.
Thread.sleep(100); // sleeps for 1/10 of a seconds in Java
Or
delay(100); // leeps for 1/10 of a seconds in Java
The simple way is that put sleep(1) in while loop. And cpu usage won't take more.

Does suspending thread make any changes?

I have a simple question
does it make any difference to try suspending a thread(in my situation)?
my thread is just an image rotator (my minSDK is 8 so must use matrix, not animation)
i have just asked a question about how to suspend a thread. everyone offered using:
while(isPaused){
try {Thread.sleep(25);}catch(...){...}
}
and my code is like this :
while(true){
//rotate image 15 deg
try {Thread.sleep(25);}catch(...){...}
}
they offer to use the first while inside the while(true)
does it make much difference ?
(I don't have to stop the thread. I can just make the rotating image invisible)
Simpler :
Does it make difference to use this to pause a thread :
while(true){
while(isPaused){
try {Thread.sleep(25);}catch(...){...}
}
//rotate image 15 deg
try {Thread.sleep(25);}catch(...){...}
}
or there isn't any problem leaving the code to rotate an invisible image ?
Edit: considering this is for a custom loading indicator, please don't use a thread. That is overkill for such a simple thing. Have a look at this answer on how to create custom loading indicators using animations.
https://stackoverflow.com/a/8129496/2910492
This has entirely to do with your application. Some more information would be useful, but in general, it seems unnatural to have an image rotating while things are supposed to be paused. Even if the image is invisible, it would (presumably) come back in a different orientation than it was when paused.
Also, the computer's resources must be consumed to continue rotating the image, which is probably not desirable. So I'd revise your code to keep things from executing while paused as such:
while(true){
if(!isPaused){
//rotation code
}
try {Thread.sleep(25);}catch(...){...}
}
Doing things this way eliminates some re-use of code. When you have a way to eliminate code and not repeat yourself, it is almost always a good idea to employ it. Repeated code means repeated errors and makes more work for you when you need to change something. If you have to copy and paste something, stop and do some soul-searching: there is most likely a better way.
You should use the "condition" instead of "true" in your while loop. That condition should be useful to complete the working of the thread.
For e.g. you may not want to make the thread orphan and keep on running even if application gets ended. So in onDestroy you can make that conditional flag false and your while loop gets failed hence thread completes it's task.

How to connect UI and functionality?

I am only a beginner in Java and until now I just put the functionality into the addActionListener() method of the buttons, it was enough for little games and stuff.
But now I am trying to make it seriously and I am wondering how to connect those 2.
As an example I am making a Fuchimi game, so I have my classes for the actual game and then a class that builds the frame with everything needed.
But my actual problem right now is, that after the frame is created, it doesn't do the following code since the code pauses at the window, like here:
FuchimiUI ui = new FuchimiUI();
//The following is not executed
Hand playerHand = null;
while (playerHand == null) {
playerHand = ui.getPlayerHand();
}
Hand enemyHand = generateHand();
ui.changeEnemyText("Enemy picked " + enemyHand.toString());
if (enemyHand.beats(playerHand)) {
ui.changeGenText("Computer wins!");
} else
ui.changeGenText("You win!");
The buttons I have just change the hand of the player.
So how can I do that properly, having the game code being compiled while the frame is already open?
I thought about threads, but I have too little knowledge about them, thus I don't know if that would be a good way.
Edit:
The ui.getPlayerHand() method returns the chosen hand(rock, paper or scissors) that the player has chosen through the buttons.
Of course I could have written the whole code in each of the button's addActionListener()methods, but I doubt that's the proper way of doing that.
So in general, all I wanted to do is let the player choose his hand and then let the game generate a random hand, then compare those two and change the text of one of the labels, depending on wether the player won or not.
The problem you are having results from the fact that your while loop is blocking the UI thread. You need to offload it to a different thread and then enqueue the UI updates back on the UI thread. The same situation is encountered here, please have a look.
There are several ways to fix this. One of them is the SwingWorker.
The steps are:
Override doInBackground for your while loop.
In it, call publish to store intermediate results (like the messages you want to display).
Override process to display the intermediate results in your UI.
The third page of above mentioned tutorial covers this.
As much as I agree with Domi's answer, that long-running code should go into a background thread, I strongly suspect that this is not what you need in this situation, that instead you should re-think the structure of your program. Likely what you need instead of that while loop is a modal dialog.
For more and better advice, consider telling us more details of the game logic and your program set up. For instance, tell us exactly what ui.getPlayerHand() does, as a start.
What you want to do is to change the structure of your program so that it is event-driven and state based where its behavior changes depending on its state. For instance if your program is in "choose hand" mode, then those buttons or other user interfaces are all that respond to the user.

Java: How to interrupt a program partway through execution with a mouseclick

How would one go about implementing a mouselistener (or some other way, doesn't matter) that will handle a mouse click event at ANY part of the program? Preferably returning to the line it left off at when the click event handler method completes.
I am using swing. The 'context' is a GUI that constantly updates, but must respond to a mouse click from the user at any time with no delay. Indeed I do have experience with events, using and overwriting their handlers etc., not too in-depth I suppose but what i do know has been sufficient in anything until now.
I could not understand your first para, so my answer goes for your second para, if I understood that correctly. ;)
Swing follows single thread model. So, you should be updating the UI from Event Dispatch Thread (EDT). This thread is responsible for delivering the events to your code too, hence the name. If you are continuously updating an UI in a loop then that is going to keep the EDT busy and blocked. The end effect will be an UI which does not respond to user events. This because the events are getting queued and EDT can pick them and deliver them to your code when it becomes free.
Games typically encounter this kind of scenario. You might have noticed that games typically have one fixed rate of refresh which they call FPS (Frames Per Second). Typically maintaining 60 FPS is good enough. That is, you need to draw your UI 50 times per second, but right now it seems that your render loop (which updates the UI) is running continuously.
You need to have separate thread continuously running which is responsible for drawing the UI. This should draw into a buffer (Image). And then invoke repaint() on the UI element to be updated. That UI element's paintComponent() needs to overridden, so that it can copy the image in Image buffer and paint that on the graphics context.
Now comes the real trick. The loop which calls repaint() must do some arithmetic to make sure it does not go beyond drawing 60 times, i.e. looping 60 times, per second. If and when it does then it must call Thread.sleep(sleepTime), where sleepTime is the number of milliseconds left in a second after looping 60 times. It might happen sometime that your loop may take more than a second to complete 60 iterations, then don't just go ahead for next iteration, but call Thread.yield(). This will give other threads a chance to use the CPU, e.g. maybe your EDT. To make the matter more complicated, do not keep yielding always, so might want to put some logic to make sure that yield for only x consecutive times. This last scenario should be very rare, if at all. This scenario means the system is under heavy load.
Remember, repaint() is thread safe and allowed to be called from any thread. It schedules a paint() call on EDT. So, calling repaint() does not guarantee a paint. So, you may want to experiment with different values of FPS to find the one which suites you.
By the way, the trick of rendering to an in-memory Image is technically called Double buffer. This gives us the ability to render nice smooth animations.
Further reading:-
LANSim - Wrote this code a long time back. You can use this code as an example.
http://java.sun.com/docs/books/performance/1st_edition/html/JPSwingThreads.fm.html
Killer Game Programming in Java - This book is on this subject.
Have you looked at SwingWorker? It's a simple framework that lets you run computations in the background and periodically publish updates to the GUI thread.

Categories

Resources