Avatar billede alex_sleiborg Nybegynder
03. april 2008 - 12:13 Der er 9 kommentarer og
1 løsning

Thread.sleep og sleep igen

Hej

jeg er helt ny til java, jeg er igang med at lave et lille spil, hvor der bliver slået med en terning. Engang imellem skal computeren slå flere gange slag. Men det går alt for stærkt, men det virker ikke ordenligt med Thread.sleep(). Den tegner ikke noget, før alle slag er slået. Hvad gør jeg?

    private void redrawDices(int DiceNumberOne, int DiceNumberTwo)
    {
            switch (DiceNumberOne)
            {
                case 1: DiceOne = new ImageIcon("images/1.gif"); break;
                case 2: DiceOne = new ImageIcon("images/2.gif"); break;
                case 3: DiceOne = new ImageIcon("images/3.gif"); break;
                case 4: DiceOne = new ImageIcon("images/4.gif"); break;
                case 5: DiceOne = new ImageIcon("images/5.gif"); break;
                case 6: DiceOne = new ImageIcon("images/6.gif"); break;
            }
            switch (DiceNumberTwo)
            {
                case 1: DiceTwo = new ImageIcon("images/1.gif"); break;
                case 2: DiceTwo = new ImageIcon("images/2.gif"); break;
                case 3: DiceTwo = new ImageIcon("images/3.gif"); break;
                case 4: DiceTwo = new ImageIcon("images/4.gif"); break;
                case 5: DiceTwo = new ImageIcon("images/5.gif"); break;
                case 6: DiceTwo = new ImageIcon("images/6.gif"); break;
            }
            lblDiceOne = new JLabel(DiceOne);
            lblDiceTwo = new JLabel(DiceTwo);
            MainPanel.add(lblDiceOne, BorderLayout.SOUTH);
            MainPanel.add(lblDiceTwo, BorderLayout.SOUTH);
            MainPanel.add(new JLabel(new ImageIcon("images/seperator.gif")));
            this.setContentPane(MainPanel);
    }

Den metode bliver kaldt fra en while løkke
Avatar billede lborupj Nybegynder
03. april 2008 - 19:21 #1
Hej,

Du bør lave et game-loop, hvor du bestemmer farten (FPS frames pr. sek).
Pseudo-agtigt bør det være noget ala:

long CYCLE = 1000 / 30;  // 1000ms / FPS = cycle time
while (game.isRunning()) {
    long start = System.currentTimeMillis();           
   
    ... perform actual game loop and repaint ...

    long duration = System.currentTimeMillis() - start;
    if (elapse < CYCLE) {
        synchronized (this) {
            wait( CYCLE - elapse );
        }
    }
}

kort sagt så siger vi at vi ønsker at få 30 frames pr. sek. Det giver 1000ms (1 sek) / 30 = 34 ms (rough), så hvert loop må tage 34 millisekunder, og hvis det tager mindre, så venter vi (wait) forskellen mellem 34ms og den faktiske tid det tog for et gennemløb (elapsed), så vi KUN kører gennem while 30 gange i sekundet.

Simpelt!  :-)
Avatar billede arne_v Ekspert
04. april 2008 - 03:22 #2
Du må ikke kalde Thread.sleep i event tråden.
Avatar billede arne_v Ekspert
04. april 2008 - 03:22 #3
Eksempel:

import java.awt.*;
import java.awt.event.*;
import java.util.*;

import javax.swing.*;

public class DynNum extends JFrame implements ActionListener {
  private JTextArea txt;
  private JButton btn;
  public DynNum() {
      setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
      getContentPane().setLayout(new GridLayout(2, 1));
      txt = new JTextArea();
      getContentPane().add(txt);
      btn = new JButton("Start");
      btn.addActionListener(this);
      getContentPane().add(btn);
      pack();
  }
  public void addNum(int n) {
      txt.setText(txt.getText() + " " + n + "\r\n");
      pack();
  }
  public void actionPerformed(ActionEvent ev) {
      if (ev.getSource() == btn) {
        T t = new T(this);
        t.start();
      }
  }
  public static void main(String[] args) {
      DynNum f = new DynNum();
      f.setVisible(true);
  }
}
class T extends Thread {
  private DynNum dn;
  public T(DynNum dn) {
      this.dn = dn;
  }
  public void run() {
      Random rng = new Random();
      for(int i = 0; i < 10; i++) {
        dn.addNum(rng.nextInt(100));
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
        }
      }
  }
}
Avatar billede arne_v Ekspert
04. april 2008 - 03:23 #4
Samme eksempel lavet mere korrekt (don't ask you don't want to know):

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class NewDynNum extends JFrame implements ActionListener {
    private JTextField txt;
    private JButton btn;
    private int n;
    public NewDynNum() {
        n = 0;
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        getContentPane().setLayout(new BorderLayout());
        txt = new JTextField();
        txt.setText(Integer.toString(n));
        getContentPane().add(txt, BorderLayout.CENTER);
        btn = new JButton("Count 10 up");
        btn.addActionListener(this);
        getContentPane().add(btn, BorderLayout.SOUTH);
        pack();
    }
    public void incr() {
        n++;
        txt.setText(Integer.toString(n));
    }
    public void actionPerformed(ActionEvent ev) {
        if (ev.getSource() == btn) {
            T t = new T(this);
            t.start();
        }
    }
    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                NewDynNum f = new NewDynNum();
                f.setVisible(true);
            }
        });
    }
}

class T extends Thread {
    private NewDynNum dn;
    public T(NewDynNum dn) {
        this.dn = dn;
    }
    public void run() {
        for (int i = 0; i < 10; i++) {
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    dn.incr();
                }
            });
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
            }
        }
    }
}
Avatar billede alex_sleiborg Nybegynder
04. april 2008 - 10:34 #5
Dit eksempel med at lave en ekstra tråd, virker på samme måde Arne. Som hvis jeg stoppede hele GUI tråden... Hvad gør jeg galt? Her er kode

Ekstra tråd

class RoleDices extends Thread
{
    private Form frm;
    public RoleDices(Form frm)
    {
        this.frm = frm;
    }
    public void run()
    {
        SwingUtilities.invokeLater(new Runnable(){public void run(){frm.roleDices();}});
        try {
            Thread.sleep(1000);
            } catch (InterruptedException e) {}
    }
}

Og eventhandler

      if (ev.getSource() == btnRole)
        {
            for (int i = 0; i < 10; i++)
            {
                  RoleDices role = new RoleDices(this);
                  role.start();  }
        }

Så slåer den 10 gange med terningen. Men de kommer på en gang alle 10 slag. Den skal slå 1 slag, vente 1 sek, slå igen, vente 1 sek osv.
Avatar billede alex_sleiborg Nybegynder
04. april 2008 - 10:39 #6
Har fået det til at virke, det er åbenbart et krav at min løkke er nede den anden klasse
Avatar billede alex_sleiborg Nybegynder
04. april 2008 - 10:40 #7
Og mange tak self. :)
Avatar billede alex_sleiborg Nybegynder
04. april 2008 - 14:06 #8
Kan du fortælle mig, hvorfor jeg ikke kan få den while løkke til at virke Arne? Havde det til at virke før, jeg flyttede det over i den anden klasse. Den skal bare springe ud af løkken når begge terninger slår 1

class RoleDices extends Thread
{
    private Form frm;
    private int nDiceOne = 1, nDiceTwo = 1;
    private int nTotalTimesRoled = 0;
    public RoleDices(Form frm)
    {
        this.frm = frm;
    }
    public void run()
    {
        boolean tmp = false;
        while(nDiceOne == 1 && nDiceTwo == 1)
        {
        roleDices();
        SwingUtilities.invokeLater(new Runnable(){public void run(){frm.redraw(nDiceOne,nDiceTwo, nTotalTimesRoled);}});
        if(nDiceOne == 1 && nDiceTwo == 1)
            SwingUtilities.invokeLater(new Runnable(){public void run(){frm.EndApp(nTotalTimesRoled);}});
        try {
            Thread.sleep(1000);
            } catch (InterruptedException e) {}
        }
    }
    public void roleDices()
    {
        nDiceOne = (int)(Math.random()*6) + 1;
        nDiceTwo = (int)(Math.random()*6) + 1;
        nTotalTimesRoled++;
    }
}
Avatar billede alex_sleiborg Nybegynder
04. april 2008 - 14:17 #9
Sorry... Bare lige en dum tanketorsk, skulle self være en do while. Smid et svar Arne, alt virker 100% nu. og mange tak
Avatar billede arne_v Ekspert
05. april 2008 - 04:45 #10
svar
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester