Particles system, a delay in an array - java

I am learning java at the moment and trying to make different features and systems. Right now I am trying to make a really simple particle system, but I have problem.
public void eDelay()
{
try
{
Thread.sleep(17);
} catch (InterruptedException e)
{
e.printStackTrace();
}
}
public void engine()
{
int i = 0;
while (i < particles.size())
{
Particle a = (Particle) particles.get(i);
eDelay();
a.move();
i = i + 1;
}
}
public void actionPerformed(ActionEvent e)
{
engine();
repaint();
}
This is a part of my code where the particles suppose to move. It works fine and they do move, but I want them to move one after another one with a delay(17). However, they move all at once and not one after another.
(particles) is an arrayList with 50 elements in it, each element containst a position for a particle.
(a.move()) is just a movement method where particle moves up.
Don't worry for the rest of the code, the problem is in this part.
Graphics, positioning of the particles, movement of the particles, and other things work fine.

Going to make my comment an answer:
"Don't worry for the rest of the code, the problem is in this part. - Graphics, positioning of the particles, movement of the particles, and other things work fine."`
How can you say this when you know what the cause of your problem is? You could be creating a Swing application (which is part of the rest of the code) and calling Thread.sleep(...) on the event thread. So make no assumptions, tell us all of the story, show more pertinent code, and let's help you solve this.
Edit: I now see that this is in fact a Swing application and so that's likely your problem, although you don't show us where the Thread.sleep is called.Calling Thread.sleep(...) puts the thread that calls it asleep, and if this is the Swing event thread (or EDT), it will put your entire application to sleep -- not a good thing to do. So don't call Thread.sleep on the event thread and use a Swing Timer instead. The tutorials will show you how.
And of course again, don't make any assumptions.

You should call repaint in the engine() loop instead of actionPerformed().

Ok guys, this is actually a bit weird but I just rewrote the engine class again into a for loop and it works.
public void engine()
{
goingcrazy = goingcrazy + gameTimer.getDelay();
for(int i = 0; i < particles.size(); i++)
{
if (goingcrazy > 1000*i)
{
Particle a = (Particle) particles.get(i);
a.move();
}
}
}
I already posted a link for the full code so if you are interested you just need to change the old engine class with the one I just posted.

Related

JFrame white and unresponsive with a while loop

I am having troubles with programming a game called "Coup" and to explain what the problem is, i need to briefly explain what the game is about. Coup is a card game where players try to eliminate each other and be the last player left. To do this, players can choose a number of actions but they can also lie to other players. In this game, other players can call "bullshit" or block another players action. Because of this, i need to make Response windows which will let other players respond with a challenge, a block or do nothing. The result of the action is then dependent on the responses. For example, a player tries to get foreign aid. I can decide to block his action or to let him continue. There are consequences if i block but that isnt the problem here.
The real problem is this: I want to give all my players a chance to give a response (Block or do nothing) via a JFrame and I use a while loop to wait for all players responses. However, this while loop doesnt do anything except keep the method from progressing since the result depends on players reactions. With the while loop, the JFrame I constructed appears white and doesnt contain the two buttons i made. At this point i can even press the close button and it wont respond due to the while loop I made which is dependent on my responseless window. Is there anyway to fix this?
if (turnCount == players[currentPlayerNum].getPlayerNum()){
for(int i=0; i<players.length;i++){
//If it is not the players turn and they have one or two lives, make response window
if (players[i].getPlayerNum() != turnCount){
if (players[i].getLives() != 0){
//foreignAidBlock constructs the response window
players[i].foreignAidBlock(turnCount);
}
else{
//Not applicable since out of game/not in game
players[i].setResponse("NA");
}
}
else{
//Not applicable since out of game/not in game
players[i].setResponse("NA");
}
}
//Idea: PAUSE TILL RESPONSES COME IN
while(players[0].getResponse() != null || players[1].getResponse() != null || players[2].getResponse() != null || players[3].getResponse() != null)
{
System.out.println(players[0].getResponse());
System.out.println(players[1].getResponse());
System.out.println(players[2].getResponse());
System.out.println(players[3].getResponse());
}
The result i get from running this part of the code is:
"NA
null
NA
NA"
continuously. I use a null to represent a player that hasnt answered yet. At the end of the method, I reset all of my players abilities back to null.
All my response window will do is change the response of the player from null to "B" or "N". But without access to the buttons I cannot do this. Does anybody have any tips on how to use something to "pause" my thread besides using a while loop?
As Abdul Fatir mentioned, it is because the UI thread is being blocked.
I would however not reccomend directly messing with threads. There is a SwingWorker class exactly for this scenario and it is reccommended you use this.
For more info check this blog article - Swing Worker Example
You can also find some useful info in the following SO question - How do I use SwingWorker in Java
Here is quick use example from the official javadoc:
Say we want to find the "Meaning of Life" and display the result in a JLabel.
final JLabel label;
class MeaningOfLifeFinder extends SwingWorker<String, Object> {
#Override
public String doInBackground() {
return findTheMeaningOfLife();
}
#Override
protected void done() {
try {
label.setText(get());
} catch (Exception ignore) {
}
}
}
(new MeaningOfLifeFinder()).execute();
The while loop is blocking your UI Thread. Perform your while loop checks in a different Thread.
Thread t = new Thread(new Runnable(){...});
t.start();
This way your UI won't be blocked and controls will remain responsive.

SnakeGame: How to deal with a interrupt thread and with a deadlock

everyone. I'm doing a game for a programming class that consists in two snakes that walk in a bord in opposite directions. They need to block in
barriers and i use coordination for them to not go against each other. Which means that the second one trying to acess a cell, will need to wait till the first unblocks the cell. I already read a lot of topics in this website and i still didn't find a solution to my problem.
Right now i already have the snakes moving all around the board and blocking in the barriers. My two big issues right e that i appreciate any help are follows ones:
1- There's specific situations, for example, two snakes walking paralell, that when they try to turn the direction towards the other snake they both block and the game
stops there, causing a deadlock. Just one can stop, while the other waits for the first one to unblock the cell. I stil didn't find a solution for the specific issue. If they don't collide
in the direction of each one, there's no problem. One snake waits for the other one to clear the cel.. i already read in here a solution about using a CountDownLatch but don't know how to implement it.
2 When the snakes blocks in a barrier, goes on wait(). Then i make her move again cliking in a cell of the board and the snake needs to recalculate a new way to go to the cell i cliked. Which means i need to change the movement from random to a specific one. The teacher said us to interrupt the thread, make her leave the method she was doing (moveNextCell() ) and recalculte the next movement again.
The problem here is that i can handle the interruption but don't know how to activate the thread again. I read it, and don't know if i interpret it bad, that after a thread it's interrupt, i can't start it again, so i need to make a copy of it. But right now i don't know how i can do it in my code since the new thread would need the actual position, color, etc of the snake.
Right now i'm not able to do both situations.
The cell code ( that blocks the snakes in case of barrier or one snake want to use the other one cell ) is the follow:
public synchronized void reserveCell(Snake snakeID){
this .snakeID = snakeID ;
while (type .equals("Barrier" )){
try {
wait();
} catch (InterruptedException e ) {
// When snake it's blocked and we interrupt it, comes to this part!
Thread. currentThread().interrupt();
snakeID.doSpecificMovement();
}
}
while (inUse ){
try {
wait();
} catch (InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
setSnakeID( snakeID);
inUse = true ;
}
The snake code ( that makes it move ) is the follow:
public void run(){
while(!Thread.currentThread().isInterrupted()){
moveNextCell( currentX, currentY); // asks the next cell, if possible adds the cell to the body of snake and updates the GUI
setRandomDirection(); // define the direction of next move.
try {
sleep(gameSpeed);
} catch (InterruptedException e ) {
// TODO Auto-generated catch block
e.printStackTrace();
}
gameOver(); // when the snakes reachs the end of the board finishs
}
}
I would appreciate any help that can make me progress in my work. Thanks for any help!
I'm assuming situations you mention in point #1 look like this:
You cannot do much about it. If snakes are separate threads, they do not know about each other and cannot themselves resolve the conflict. Your professor should specify how to resolve such deadlocks. The simplest solution would be to keep the snakes deadlocked until user interacts and chooses different destination. You can also add timeout to wait() method. If cell doesn't become available after some time, randomly choose different direction.
There are two ways to solve the second issue:
You can stop the thread completely and then start new thread with new destination. You would have to remove InterruptedException from all catches and propagate it up to run() method:
void goToDestination() throws InterruptedException {
...
}
#Override
public void run() {
try {
goToDestination();
} catch(InterruptedException e) {
// end thread
return;
}
}
This way interrupt() will be able to stop the thread. You can restart it like this:
// interrupt and wait until thread actually finishes
snake.thread.interrupt();
snake.thread.join();
// change the destination
snake.destination = newDestination;
// restart the thread
snake.thread = new Thread(snake);
snake.thread.start();
You can also change the destination and interrupt just the main method:
#Override
public void run() {
while(true) {
try {
goToDestination(destination);
} catch (InterruptedException e) {
// try again with changed destination
}
}
}
When user chooses new destination:
// set new destination
snake.destination = newDestination;
// interrupt old goToDestination
snake.thread.interrupt();
banthar, i just tried your second solution and worked great! I would never thought about this, all this exception things it's really a new thing to me!
Like before, i'm gonna say what i did in order to help the others.
As banthar said, all methods that i was using that would lead to the interrupt, i put them going to the run() of the snake. So this way i was able to stop the thread and make a new one. Then i just add to use a method to change the direction and make a new start like banthar put.
Problem solved, thank you very much and hope this can help more people!
About the first issue, i already solved it. In case someone find this useful for their problem, i'm gonna post my solution.
The problem, as Banthar said, is that the snakes don't know about the other ones. Which means that in this specific two situations, they would block each other, waiting for the other to move => Deadlock.
The solution here is for one of them warn the other "Hey Snake, i'm blocked. Don't block waiting for me or we both get stuck".
Searching the internet i found a lot of solutions using a ThreadPool that would coordinate all them but that was just to much for my problem.
So i made a atrribute in Snake called snakeBlocked that turns true whhen the snakes blocks. The operation is made in the Cell when the snake trys to acess it. So when the second snake trys to acess a cell with a snake, the cell have a method to find out what's the value of the snakeBlocked of the snake stuck in the cell. After that turn out easy.
If the snake that wants to acess the cell knows there's a blocked snake there, she changes her direction.
Hope it can help someone since i was stuck in those for a long time.
About the issue #2 gonna try it now, after i come here if i can come to a solution!

Java graphics not updating correctly

In my program, a the graphics on my screen are supposed to move across the screen. I have a loop that calls the draw function(the draw function is display.draw()), but whenever the amount of times the loop runs is greater than one, the display doesn't update after each time like it should. Instead, it waits until the loop finishes to update the display.
below is the refreshing function that only apparently runs at the end.
public void refresh()
{
myPanel.removeAll();
myPanel.add(display.draw());
myPanel.validate();
myPanel.repaint();
}
And here's the loop. I added a 1 second sleep after each iteration to make sure it just wasn't moving faster than I could see.
for(int i = 0; i < 2; i++)
{
myGraphics.rearrange();
this.refresh();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
}
}
myGraphics.rearrange() simply changes the values of the variables which the drawing function uses,
changing the x and y variables for the positions of all the objects.
What is happening that it's not updating?
You're calling Thread.sleep(...) in a Swing program on the Swing event thread. What this does is put the entire application to sleep and so is not something that you should be doing. Instead use a Swing Timer to drive your animation.
For example:
Similar question 1
Similar question 2
Similar question 3
For more specific help, consider posting more code, preferably an mcve.

What is the best practice for determining when a Canvas has been resized?

Ok so I've been working on a graphing calculator for quite some time and early on in the project I implemented a somewhat robust window listener. Or should I say I built a robust window listener to handle updating local variables whenever the window size changed. What I basically did was this...
/*
canvas, canvasWidth, canvasHeight and refreshGrid() are all local to this class
*/
private class resizeCatch extends Thread{
private boolean refreshOnStop = false;
public void run(){
while(true){
if(canvasWidth != canvas.getWidth() || canvasHeight != canvas.getHeight()){
canvasWidth = canvas.getWidth();
canvasHeight = canvas.getHeight();
refreshOnStop = true;
}else if(refreshOnStop && canvasWidth == canvas.getWidth() && canvasHeight == canvas.getHeight()){
refreshOnStop = false;
refreshGrid();
}
try{Thread.sleep(100);} catch(InterruptedException e) {}
}
}
}
I start this Thread when my Plotter object is instantiated and all it does is check the canvas's size and compare it to it's internal variables. When there's a difference update the variables, trigger an update to happen and when the difference(s) cease update the graphical side of things and continue listening for a change.
I understand that this is a common practice.
However I've been generalizing my Plotter window, I've made it more deployable and it doesn't necessarily have to manage it's own window anymore which is why I felt like it was time to kick this nasty eye sore to the curb! I still however have the issue with when to refresh the graphics... The obvious answer is when the canvas changes size but how do I know?
Ideally somewhere buried in the manuals (oh and believe me I've read the manuals thoroughly these last few months...) there lies some kind of WindowEventListener or ContainerListener that has a ResizeEvent or some kind of colloquial jargon I'm not familiar with. However I can not find anything!
While the idea of having extraneous Thread class's nested in my program with the infamous while(true) doing the dirty work of something as mundane as re-sizing components titillates me (NOT) I have to find some sort of alternative. So that kind of brings me back to the root of my question. What is the proper way to listen for and trigger a response to the dimensions of a container changing and if there are no right ways what practices have you put together that are lightweight, manageable and reasonable?
I've been able to ignore this for almost half a year now and as I near the finish of my program this is something I desperately want to get rid of. Please extend a helping hand :)
Alright so giant hat tip to MadProgrammer for pointing out the ComponentListener to me. Which while taking some time worked perfectly and exactly how I wanted. I know this question baffles a lot of people so I'll be a bit more verbose then most tutorials and explain the few simple steps to integrate a ComponentListener for the resizing of a window.
Step One: Import the correct libraries
import java.awt.event.ComponentListener;
import java.awt.event.ComponentEvent;
Step Two: Implement the listener to your class
public class Plotter extends GCanvas implements ComponentListener{
Step Three: Add your Object to the ComponentListener
this.addComponentListener(this);
Step Four: Override the following methods
public void componentResized(ComponentEvent e){
//do whatever you want upon size change
}
public void componentHidden(ComponentEvent e){
//do whatever you want upon visibility change
}
public void componentMoved(ComponentEvent e){
//do whatever you want upon location change
}
public void componentShown(ComponentEvent e){
//do whatever you want upon visibility change
}
That's pretty much it. Once these tools are in place you're in business! Enjoy :)

Alternating images with a timer using java

Since I'm not a CS major, I'm having some difficulties translating my programming wishes into an actual program.
What it basically boils down to is the following: how can I alternate an image on a label, showing each image for an amount of tim specific for each image.
So: say I've images A and B; I'd like the user to see A for 1000ms and B for 200ms. This keeps on looping until a user presses a certain key.
Now, I'm able to load an image onto a panel, quite easily even, and I've managed to catch user input using KeyListener and stuff, which all works quite nicely and alot easier then I had expected. I also know how to use looping constructs like while, for and do..while, but this timer business is shady.
I see all kinds of stuff using threads and what not, I really don't need that. This is not about efficient programming or good code, it's simply about demonstrating something.
Any help would be greatly appreciated!
Use a SwingWorker<Void, Void>. The doInBackground method of the SwingWorker should look like this :
#Override
protected Void doInBackground() {
try {
while (true) {
displayImage(imageA);
Thread.sleep(1000L);
if (isCancelled()) {
return null;
}
displayImage(imageB);
Thread.sleep(200L);
if (isCancelled()) {
return null;
}
}
}
catch (InterruptedException e) {
// ignore
}
return null;
}
private void displayImage(final Icon image) {
SwingUtilituies.invokeLater(new Runnable() {
#Override
public void run() {
// display the image in the panel
}
});
}
The keylistener should simply cancel the SwingWorker.
Here's something that might be a good example:
http://www.java2s.com/Code/Java/Development-Class/UsejavautilTimertoscheduleatasktoexecuteonce5secondshavepassed.htm
I can try to explain the code if it appears confusing
There is nothing necessarily inefficient about using threads when threads are the right tool for the job.
In this case, it would not be unreasonable to create a new class that implements Runnable, which holds a reference to the label you wish to change the image on.
This means that the image could be changed without causing waits on the main application that would cause it to hang until it was done.
You would want to avoid 'Busy Loops' [basically, a while loop with no Thread.sleep() within it], and look to see if there is any needed thread exit criteria

Categories

Resources