I have a couple different enemy types and enemyManager arrayList classes for each type. I have each type of enemy randomly spawning at spawn points slightly off screen, coming onto the screen, then off the other side, dying, and randomly responding. The problem is when I use a loop to spawn the objects many of them spawn in the same place or catch up with each other die around the same time and spawn again. I would like to have a delay between them so they are more spread out.
What I am looking for is a way to slow down the looped spawning of enemies in java. I tried extending enemy manager classes by timer and naming the spawn function run but this didn't work.
Also I am not multithreading because I don't really know how to set that up yet and was trying to finish this project without implementing that, but if that seems like the best solution then I guess I will have to.
thanks for any suggestions.
updated .....
class spawnLgCars extends TimerTask {
public void run() {
if (lgCars.size() < 10) {
lgCars.add(new LgCar());
System.out.println("spawned");
} else if (lgCars.size() > 10) {
lgCars.get(0);
}
}
}
Here I how I'd like to implement TimerTask, but because it had to be in it's own class it didn't have access to the properties of the instance of lgCars I was using. Then I tried adding extending lgCars by Timer Task and calling the task in the constructor, but this also didn't work. not sure why.
TimerTask and a java.util.Timer won't work because it is not set up to run the repeated code on the Swing event thread and should be avoided with Swing GUI's. Again you should use a Swing Timer since all the code that is called in the Timer's ActionListener is called on the Swing event thread.
On the other hand, if you have a long running task, such as if you wanted to do image analysis or something else that takes a long time to run, then that should be called in a background thread such as via a SwingWorker.
Related
I am currently working in a implementing a quoridor game in java , using AI game-playing algorithms. After the "human" clicks to make his move , the gui needs to be updated and the AI start thinking.
I have something like this inside the panel:
public void mouseClicked(MouseEvent e)
{
gameBoard.executeMove( movePawn );
repaint();
gameboard.callAi();
}
After I call the funtcion callAi() , I get into a loop that is consuming too much time to finish. The gui on the other hand freezes , it doesnt update , even thought the repaint method is called before the AI "start thinking". I tried to put a delay before I call the AI , but it was not working. I wrote this one:
try
{ TimeUnit.MILLISECONDS.sleep(5);}
catch{}
What can I do to solve this one ? Maybe it has something to do with threads , but I am not too friendly with threads in Java.
I would highly recommend reading up on what the EDT (Event Dispatch Thread) is.
Java Event-Dispatching Thread explanation
One of the answers does a good job explaining it. Quick TLDR: Basically one of the reasons the GUI freezes is because of the AI method you included on the EDT (I can't say for certain about the gameBoard.executeMove(...) method). EDT is meant for updating the GUi, not running methods that take a lot of compute time.
Get the game logic code out of the GUI and into the main thread/new thread (not the EDT). If you absolutely need game logic inside the EDT then make a new Thread in the EDT, have it do its game calculations, and finally use Swing.Utilties.invokeLater(...) method to update the GUI.
Maybe it has something to do with threads , but I am not too friendly with threads in Java.
Definitely want to get familiar with threads when you are making a game, specially the EDT.
You should use a SwingWorker to do the AI work on this. All the updating and processing happens on a single thread within Swing so if you block that then you will freeze the UI.
https://docs.oracle.com/javase/tutorial/uiswing/concurrency/worker.html
I've got some problems while learning threads in Java. The goal is to make a simulation that shows us how rabbits are running from wolves on some kind of board. Every wolf and every rabbit should be a thread. So I created a GUI in main method of Test class and created a new class that implements the Runnable interface. That's easy and logical I think. But now, how can I call the AddRabbit method from these threads? Because very thread should do mething like:
Change its properties like place on the map
Check other threads place on the map
Paint itself on the panel
But how?
Updating Swing components directly using multiple threads is not allowed--Swing is not threadsafe. There is a single Swing event queue that it processes, so if you have to update a JComponent in an existing thread, you will use the following code:
//You are currently in a separate thread that's calculating your rabbit positions
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Put in code to modify your Swing elements
}
});
So every time you feel the need to update your GUI, then you can pass an instance of Runnable onto the Swing event queue using the SwingUtilities.invokeLater method, which it will process in its own thread.
A continuation, suggested here, is a good choice for updating the GUI from multiple threads, but it may be difficult to correctly synchronize access to shared data.
Alternatively, use a javax.swing.Timer to periodically update a model that manages the properties of wolves and rabbits. A related example of objects moving on a grid is examined here. For greater flexibility, use the Model–View–Controller pattern, illustrated here.
Hello have only a few days with Java and android here. I am a bit confused about exactly how the "implements runnable" actually works example:
public class DrawableSurfaceView extends SurfaceView implements Runnable {
[...]
public void resume(){
isRunning = true;
mThread = new Thread(this);
mThread.start(); //start the animation
parseParameters(); //<== Here is my problem
}
public void run() {
while (isRunning == true){
if (!mHolder.getSurface().isValid()) {
continue;
}
Canvas canvas = mHolder.lockCanvas();
canvas.drawARGB(255, 0, 0, 0);
canvas.drawPath(PenPath, PenPaint);
canvas.drawPath(CursorPath, CursorPaint);
mHolder.unlockCanvasAndPost(canvas);
}
}
public void parseParameters() {
[...]
[ The rest of my code here modifying PenPath and CursorPath, etc ]
}
I am embarrassed to ask, but I thought that after mThread.start(); a new thread would be started running a loop in the run method. instead what I get is the run method only executed after my parseParameters() method terminates.
What I wanted to achieve is to have the canvas on a drawing loop thread and externally modify the parameters of the drawing paths to generate my animation.
I am sure this is very elemental, but I have been unable to understand this for a few hours. The docs are not helping.
Any pointer would help a lot. Cheers guys!
The meaning of implements Runnable is that this class reacts to the methods defined in the Runnable interface, and those may be passed to the constructor of Thread as you do.
Now, a new thread is not immediately executed, and it is very possible that the current thread will continue to execute some function before the system will switch to the other thread's context.
mThread.start(); only tells Java (and the OS) to make the thread eligible to run. There's no guarantee that the thread will start right away. In fact, especially on a single-core system, the thread often won't start running til the next time the OS jumps in and switches tasks/threads, so when it'll actually start can be pretty much "when it feels like it".
Class X ... implements Runnable only do one single thing, namely promise that X will provide what the Runnable interface say will be there. In other words, it is an indication that X will conform to the contract that a Java interface - here Runnable - is.
For Runnable the only thing the contract say, is that X will provide a void run() method.
The trick here is recognizing that the Thread constructor called require a Runnable, so it can be certain there is a run() method to invoke. Note that when the new thread has started, your program now has two places where things happen. You need to be certain to assign the work correctly, so it happens in the correct thread.
Your understanding of Runnable is basically correct.
The problem is that you are making incorrect assumptions about what Thread.start() does. In reality, Thread.start() causes the new native thread and its stack to be created, and makes the thread eligible to run. But it is implementation dependent whether the new thread is scheduled and runs before the start call returns to the original thread ... or not.
The other problem with your code is that run() method is essentially a CPU gobbling polling loop. Unless you are running on a platform with multiple cores, your application's behaviour is going to be very "laggy" ... and it will rapidly drain the batteries. You need to make it event driven, with the run() method waiting until there is something to actually draw.
I don't know enough about Android to tell you how to implement that, but what your app is currently doing looks very wrong to me.
It seems that in this situation you would not want to implement any kind of loop yourself. You would want to override the onDraw(Canvas canvas) in your custom view. With this you can force onDraw to be called by calling invalidate() on your view from anywhere. You could accept parameters from an outside source as well.
I'm currently trying to get a small brick-breaker game I made to effectively use some form of power-ups or bonuses. I have have it mostly implemented right now. However I have a problem. I use java.util.Timer to determine how long the power-up lasts. Most likely, that power-up is going to be chosen (by a random number generator) more than once. However, a Java Timer can only be used once, and after it's cancel() method is called, it's done. Right now, I set up the game to mark a power-up as used and to never use it again. Is there a way to get around this? Here's the method that is called when the LongPaddle power-up is chosen:
public void longPaddleTime(int seconds) { //longPaddle Timer Method - gets called when the longPaddle bonus is enabled; shuts off longPaddle after a set amount of time
timerLP.schedule(new TaskLP(), seconds*1000);
}
class TaskLP extends TimerTask { //The task to be run after the timer in longPaddleTime runs out
public void run() {
longPaddle=false; //Disable LongPaddle
bonusActive=false;
LPused=true; //Mark as used
timerLP.cancel(); //Terminate the timer thread
timerLP.purge();
}
}
You don't need to cancel() your timer - Timer.schedule(TimerTask, long delay) will only run the specified task once. You only need to cancel() a timer if you want to terminate everything it's doing.
For your case (scheduling a task once), there's no cleanup required in the Timer class. If you had a repeating task and you wanted to stop just that one task, you could call TimerTask.cancel() to prevent it from reoccuring, while still allowing the Timer to be reused for other purposes.
You don't have to cancel the timer in your TaskLP.
Create a Timer object that lives in Application scope and just schedule new TimerTasks as need arises.
BTW, although not officially deprecated, Timer functionality has been superseeded by ScheduledExecutorService. I suggest, if you start from scratch to use this framework.
Executors utility class has a few methods that simplify the construction of the ScheduledExecutorService.
I have a swing application which stores a list of objects. When the users clicks a button,
I want to perform two operations on each object in the list, and then once that is complete, graph the results in a JPanel. I've been trying SwingWorker, Callable & Runnable to do the processing, but no matter what I do, while processing the list (which can take up to a few minutes, as it is IO bound), the GUI is locked up.
I have a feeling it's probably the way I'm calling the threads or something, or could it be to do with the graphing function? That isn't threaded as it is very quick.
I have to do the two processing stages in order too, so what is the best way to ensure the second one has waited on the first? I've used join(), and then
while(x.isAlive())
{
Thread.sleep(1000);
}
to try and ensure this, but I'm worried this could be the cause of my problem too.
I've been looking everywhere for some pointers, but since I can't find any I'm sure I'm doing something stupid here.
The problem is, your long running task is blocking the Thread that keeps the GUI responsive.
What you will need to do is put the long running task on another thread.
Some common ways of doing this are using Timers or a SwingWorker.
The Java tutorials have lots of information regarding these things in their lesson in concurrency.
To make sure the first task finishes before the second, just put them both on the same thread. That way you won't have to worry about keeping two different threads timed correctly.
Here is a sample implementation of a SwingWorkerFor your case:
public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
private List<Object> list
public YourClassSwingWorker(List<Object> theOriginalList){
list = theOriginalList;
}
#Override
public List<Object> doInBackground() {
// Do the first opperation on the list
// Do the second opperation on the list
return list;
}
#Override
public void done() {
// Update the GUI with the updated list.
}
}
To use this code, when the event to modify the list is fired, create a new SwingWorker and tell it to start.
You are not returning the swing thread properly. I realize you are using callable/runnable but i'm guessing you are not doing it right (although you didn't post enough code to know for sure).
The basic structure would be:
swingMethod() { // Okay, this is a button callback, we now own the swing thread
Thread t=new Thread(new ActuallyDoStuff());
t.start();
}
public class ActuallyDoStuff() implements Runnable {
public void run() {
// this is where you actually do the work
}
}
This is just off the top of my head, but I'm guessing that you either aren't doing the thread.start and are instead calling the run method directly, or you are doing something else in the first method that locks it up (like thread.join). Neither of these would free up the swing thread. The first method MUST return quickly, the run() method can take as long as it wants.
If you are doing a thread.join in the first method, then the thread is NOT being returned to the system!
Edit: (Second edit actually)
I think to speak to the problem you are actually feeling--you might want to think more in terms of a model/view/controller system. The code you are writing is the controller (the view is generally considered to be the components on the screen--view/controller are usually very tightly bound).
When your controller gets the event, it should pass the work off to your model. The view is then out of the picture. It does not wait for the model, it's just done.
When your model is finished, it needs to then tell the controller to do something else. It does this through one of the invoke methods. This transfers control back to the controller and you go on your merry way. If you think about it this way, separating control and deliberately passing it back and forth doesn't feel so bulky, and it's actually very common to do it this way.
It sounds like the problem might be that you are waiting on the threads to finish from inside the GUI thread. Your GUI thread should not wait on these threads, instead you should have the worker threads invoke some method on the GUI thread that sets a flag. When both flags are set then you know both threads finished and you can do the graph.
I can't really speak to the swing threading model, but:
I have to do the two processing stages in order too, so what is the best way to ensure the second one has waited on the first?
For this kind of functionality, I'd suggest you create two worker threads, and embed a JMS broker. Deliver work to the two threads by passing messages into JMS queues that they read from. Your GUI thread is free to examine the queues to determine when work is happening and represent the state of play in your UI.
The solution to my problem was a mixture of jjnguy and Bill K's answers, so thanks very much for that guys. I needed to use threads within a SwingWorker like this:
public class Worker extends SwingWorker<Void, Void>
{
private List<Object> list;
public YourClassSwingWorker(List<Object> theOriginalList){
list = theOriginalList;
}
#Override
public List<Object> doInBackground() {
Thread t = new Thread(new ProcessorThread(list));
t.start();
}
#Override
public void done() {
// draw graph on GUI
}
}
class ProcessorThread implements Runnable {
//do lots of IO stuff
Thread t2 = new Thread(new SecondProcess());
t2.start();
}
This made sure all the work was being done by worker threads away from the GUI, and also ensuring that the SwingWorker itself wasn't doing all of the work, which might have been a problem.