I am trying to create a loading state in the beginning of the game with the company information while it loads some files. The problem is when i use sleep on it. It will not draw the background. If i use wait it returns an error because it needs an objeft. Is there an easy way to do this? Draw a background using a sprite batch and then wait before pushing a new state? thanx
#Override
public void render(SpriteBatch sb) {
sb.begin();
Object obj = new Object();
sb.draw(bk, 0, 0, 56, 56);
try {
TimeUnit.SECONDS.sleep(5);
gsm.push(new MenuState(gsm));
dispose();
} catch (Exception e) {
System.out.println("error");
}
sb.end();
I have also tried this:
TimeUnit.SECONDS.wait(obj, 5);
TimeUnit.SECONDS.timedwait(5);
wait();
Thread.Sleep();
//all in try catch block
I have also tried to seperate into its own thread and failed. There has to be an easy way to do this no?
public void timer(){
try {
TimeUnit.SECONDS.sleep(3);
} catch (Exception e) {
System.out.println("error");
}
}
#Override
protected void handleInput() {
if (load)
{
timer();
gsm.push(new MenuState(gsm));
dispose();
}
}
#Override
public void update(float dt) {
handleInput();
load = true;
}
Related
I am trying to render a loading animation on top of a nattable. I use the OverLayPainter mechanism to draw a "glasspane" and some text on top of the table, and this works perfect:
public class MessageOverlay
implements IOverlayPainter {
....
#Override
public void paintOverlay(final GC gc, final ILayer layer) {
this.currentGC = gc;
this.currentLayer = layer;
if (visible) {
currentGC.setAlpha(200);
currentGC.fillRectangle(0, 0, currentLayer.getWidth(), currentLayer
.getHeight());
drawMessage();
if (withLoadingAnimation) {
showAnimation = true;
}
} else {
showAnimation = false;
}
}
}
However, the paintOverlay method is not called regularely but rather everytime the table changes.
To be able to display a smoothe animation, I added a new thread
final Thread animatorThread = new Thread(new Runnable() {
#Override
public void run() {
while (!Thread.interrupted()) {
try {
Thread.sleep(1000 / fps);
} catch (final InterruptedException e) {
break;
}
display.asyncExec(new Runnable() {
#Override
public void run() {
if (showAnimation && !currentGC.isDisposed()) {
final Image currentImage = getNextImage();
final int posX = currentGC.getClipping().width / 2
- currentImage.getBounds().width;
final int posY = currentGC.getClipping().height / 2
- currentImage.getBounds().height;
currentGC.drawImage(currentImage, posX, posY);
}
}
});
}
}
});
animatorThread.start();
As you can see it tries to access the graphics context this.currentGC set in the paintOverlay method. My problem is, that currentGC within the animatorThread is always disposed.
How can I a.) ensure that the context is not disposed in the thread or b.) solve this in an alternative way?
Thanks for the help.
You could try to create a new GC with the current NatTable instance and if needed pass the config from the passed in GC instance. Then you are in charge of disposing the GC instance and should not have the risk of a disposed GC outside your thread.
A simple example could look like the following snippet that simply shows the pane for 1000ms and then removes it again. You need of course to change the logic to be more dynamic with regards to your loading operation then:
AtomicBoolean paneThreadStarted = new AtomicBoolean(false);
...
natTable.addOverlayPainter(new IOverlayPainter() {
#Override
public void paintOverlay(GC gc, ILayer layer) {
if (this.paneThreadStarted.compareAndSet(false, true)) {
Display.getDefault().asyncExec(new Runnable() {
#Override
public void run() {
GC currentGC = new GC(natTable);
currentGC.setForeground(GUIHelper.COLOR_WHITE);
currentGC.setBackground(GUIHelper.COLOR_BLACK);
currentGC.setAlpha(200);
currentGC.fillRectangle(0, 0, layer.getWidth(), layer.getHeight());
String load = "Loading data ...";
Point textExtent = currentGC.textExtent(load);
currentGC.drawText(load,
layer.getWidth() / 2 - textExtent.x / 2,
layer.getHeight() / 2 - textExtent.y / 2,
true);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentGC.dispose();
natTable.redraw();
}
});
}
}
});
This way you are able to show the pane again by changing the AtomicBoolean from the outside:
Button showPaneButton = new Button(buttonPanel, SWT.PUSH);
showPaneButton.setText("Show Pane");
showPaneButton.addSelectionListener(new SelectionAdapter() {
#Override
public void widgetSelected(SelectionEvent e) {
this.paneThreadStarted.set(false);
natTable.redraw();
}
});
I am using a thread to draw images onto a JFrame.
I added a keyListener to listen for the key P, when it is pressed, the drawing of images stops and when I press P again, the drawing should resume.
I tried using wait/ notify along with synchronized block for implementing this.
However only Pausing works, the resume never works.
Strange...
public static void main(String[] args)
{
static JFrame window1 = new JFrame();
static boolean isPaused=false;
Runnable r = new Runnable()
{
public void run()
{
while(true)
{
window1.paintImage();//fn to redraw an image
}
}
};
final Thread t = new Thread(r);
window1.addKeyListener(new KeyListener()
{
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_P)
{
if(isPaused==false)
{
synchronized(t)
{
try
{
t.wait();
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
isPaused=true;
} else
{
t.notifyAll();
isPaused=false;
}
}
}
public void keyReleased(KeyEvent arg0){}
public void keyTyped(KeyEvent arg0){}
});
t.start();
}
}
You should go through the Javadoc of Object.wait.
When t.wait() is executed, the current thread is "paused", not t.
More exactly, you are pausing the SWING Thread that is in charge of handling inputs, not the Thread t that you created to redraw the image.
t.wait() makes the SWING Thread to wait until it receive a notify() which will never come because the t.notifyAll() can only be reached by this same SWING Thread (so it is like you are going to sleep and you are waiting for yourself to wake you up... good luck with that).
Here is one solution to fix it (not the best though, since it does not care about synchronization):
final boolean [] pause = new boolean []{false};
Runnable r = new Runnable()
{
public void run()
{
while(true)
{
if(!pause[0])
window1.paintImage();//fn to redraw an image
}
}
};
...
public void keyPressed(KeyEvent e)
{
if(e.getKeyCode() == KeyEvent.VK_P)
{
if(!pause[0])
{
pause[0] = true;
} else
{
pause[0] = false;
}
}
}
Java.problem is when i start addding new element repaint stops every time for a moment while timer is working and elements are moving finaly when it repaints elements just jump like thay have been moving all this time.also there is throwing strange exeption. some code:
public void paintComponent(Graphics g)
{
g = (Graphics2D) g;
g.drawImage(img1, 0, 0,null);
Iterator<zombie> it = zombies.iterator();
while(it.hasNext())
{
if(it.next().heals <= 0)
{
it.remove();
}
else{
g.drawImage(it.next().img ,it.next().x , it.next().y , null);
}
}
}
public void actionPerformed(ActionEvent e)
{
Iterator<zombie> it = zombies.iterator();
while(it.hasNext())
{
it.next().move();
}
repaint();
}
that is new thread that generates new items:
public void run()
{
Random rd = new Random();
while(true)
{
try {
Thread.sleep(1000 + rd.nextInt(2000));
if(rd.nextInt(4) == 1)
{
zombies.add(new ZombieLow(1000,rd.nextInt(500),1,20,300));
}
else
{
zombies.add(new ZombieHard(1000,rd.nextInt(500),1,15,700));
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
}
what is that problem with? if you need more info just say i will give it.
try to put the repaint() method in the while loop. In your case you repaint your Zombie after moving all.
another thing if you use Thread.sleep() in the move method you should make every Zombie in his own Thread.
Hope that helps, Salam =)
I'm using a button to start a background service in my app. This is the code I'm using:
#Override
public void actionPerformed(ActionEvent action) {
if (action.getActionCommand().equals("Start")) {
while (true) {
new Thread(new Runnable() {
public void run() {
System.out.println("Started");
}
}).start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
This does update the service every second, which it what I want. Problem is it freezes the rest of the application. How do I implement it so that that doesn't happen?
The following is likely to cause your application to pause:
while (true) {
...
}
Try removing those lines.
Edit: as per comment, to make the newly-launched thread fire every second, move the sleep and while loop inside the run() method:
if (action.getActionCommand().equals("Start")) {
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("Started"); }
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
You're calling this method in the Thread that updates the GUI, and this you're pausing the GUI refresh. Spawn a new thread and execute that there.
an infinite loop ??
while (true) {.....}
how you supposed to get out of here -
add an print statement inside loop and you will come to know that you have been stuck here after button click
Ok I got it. Here's what I should have done:
#Override
public void actionPerformed(ActionEvent action) {
if (action.getActionCommand().equals("Start")) {
new Thread(new Runnable() {
public void run() {
while (true) {
System.out.println("Started");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}
Im writing a simple game in Java. Here is main code:
public class MainPanel extends JPanel {
private Player player = new Player(100, 100, 3, 3);
private Point2D targetPoint = new Point2D.Float(130, 350); //Pos on begin
private ArrayList<Beam> beams = new ArrayList<Beam>();
public MainPanel() {
setPreferredSize(new Dimension(300, 400));
addMouseMotionListener(new MouseMotionHandler());
//Add shortcuts
makeShortcut("player.BM1", "F1", new SetBeamModeAction(1));
makeShortcut("player.BM2", "F2", new SetBeamModeAction(2));
//Start threads
Thread t = new Thread(new PlayerMoveRunnable());
t.start();
Thread t2 = new Thread(new PlayerShootRunnable());
t2.start();
}
public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D)g;
g2.setColor(Color.BLACK);
g2.fillRect(0, 0, 300, 400);
//Draw player
g2.drawImage(player.getImage(), (int)player.getX(), (int)player.getY(), null);
//Draw beams
for (Beam beam : beams) {
g2.drawImage(beam.getImage(), (int)beam.getX(), (int)beam.getY(), null);
}
}
//Thread running all the time
private class PlayerMoveRunnable implements Runnable {
public void run() {
try {
while (true) {
player.moveToPoint(targetPoint);
repaint();
Thread.sleep(15);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//Thread working all the time
private class PlayerShootRunnable implements Runnable {
public void run() {
try {
while (true) {
//Choose which beam to shoot (depends on set mode)
Thread t;
switch (player.getBeamMode()) {
case 1:
t = new Thread(new BeamMoveRunnable(new Beam1(player.getX()+18, player.getY(), 0, -15)));
break;
case 2:
t = new Thread(new BeamMoveRunnable(new Beam2(player.getX()+18, player.getY(), 0, -30)));
break;
default:
t = null;
break;
}
t.start();
Thread.sleep(200);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private class BeamMoveRunnable implements Runnable {
private Beam beam;
public BeamMoveRunnable(Beam beam) {
this.beam = beam;
}
public void run() {
Beam beam = this.beam;
beams.add(beam);
try {
while (true) {
if (beam.getY() <= 0) {
beams.remove(beam);
break;
}
beam.move();
repaint();
Thread.sleep(20);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
[its not whole code. I cut few lines which for sure arent causing problem]
Im getting such error:
Exception in thread "AWT-EventQueue-0" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at spacecommander.MainPanel.paintComponent(MainPanel.java:53)
at javax.swing.JComponent.paint(JComponent.java:1054)
and so on...
Where lies the problem? I know what ConcurrentModificationException means but I dont know where can be the problem here.. Maybe I should make some synchronization. If yes please show where
You are modifying the list of beams in another thread e.g. BeamMoveRunnable while you are iterating over the collection.
Creating a thread per object is pretty wasteful and difficult to manage.
I suggest you have a one thread which periodically calls a method on each beam to move. I suggest you not add or remove the beams while they are being drawn so you won't have to synchronize access to the collection.
Before iterating the beams in paintComponent create a copy of the collection and use the copy to iterate.
You are modifying the array list beams in the thread BeamMoveRunnable (the thread which wraps this Runnable object) simultaneously with iterating it in the method paintComponent. This is the cause for the exception.