2015-06-30 5 views
1

Я работаю над сырой игрой (думаю, CookieClicker), используя JFrame gui по умолчанию. Единица валюты - это «клики», и когда достаточно «кликов» заработано, игрок должен иметь возможность щелкнуть JButton, соответствующую автокликеру, который они могут купить. Тем не менее, только последний «автокликкер», добавленный в ArrayList автокликеров, становится доступным в нужное время, и если он щелкнут, все остальные JButtons получат свои свойства. Если возможно, не могли бы вы помочь мне разобраться с проблемой? Отказ от ответственности: возможно, проблема устранения неполадок.JButton ArrayList не обновляется корректно по тику?

Вот мой Основной класс: (у меня есть дополнительное JButtons и автокликер закомментированное поэтому она работает вроде как задумано)

import java.awt.FlowLayout; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.util.ArrayList; 
import java.util.Arrays; 

import javax.swing.*; 

public class Main extends JFrame /*implements Runnable*/{ 

    static double clickCount = 0D; 
    static double cpst = 0D; 
    static JFrame frameMain = new JFrame("Clicker - Evan"); 
    static JLabel labelCount = new JLabel("Click Count: " + clickCount); 
    static JLabel labelcps = new JLabel("Click Per Second: " + cpst); 
    static ArrayList<AutoClicker> clickers = new ArrayList<AutoClicker>(/*Arrays.asList(AutoClicker("Mouse", 1, 10))*/); 
    static ArrayList<JButton> buttonAuto = new ArrayList<JButton>(); 

    static JButton buttonMain = new JButton("Click"); 

    private static boolean running = false; 
    //private Thread thread; 

    public static void main(String[] args){ 
     init(); 
     run(); 
    } 

    static long lastTime2 = System.nanoTime(); 
    final static double amountOfTicks2 = 2D; 
    static double ns2 = 1000000000/amountOfTicks2; 
    double delta2 = 0; 

    //Reference: https://www.youtube.com/watch?v=jEXxaPQ_fQo 
    static class buttonMainAction implements ActionListener{ 
     public void actionPerformed(ActionEvent e){ 
      clickCount++; 

      System.out.println("refresh?"); 


     } 
    } 
    static class buttonBuyAction implements ActionListener{ 
     public void actionPerformed(ActionEvent e){ 
      int fromNumber = Integer.parseInt(e.getActionCommand()); 

      clickCount -= (int)clickers.get(fromNumber).getCost(); 
      clickers.get(fromNumber).buy(); 
      buttonAuto.get(fromNumber).setText(clickers.get(fromNumber).getNumberOwned() 
        + " " + clickers.get(fromNumber).getName() + "(s) - Cost: " + (int)clickers.get(fromNumber).getCost() + " Clicks"); 

      System.out.println("+1 " + clickers.get(fromNumber).getName()); 
     } 
    } 


    //Source: https://www.youtube.com/watch?v=qSdKBQMdlLM 
    //Source 2: https://www.youtube.com/watch?v=vFRuEgEdO9Q&list=PLah6faXAgguMnTBs3JnEJY0shAc18XYQZ&index=4 
    public static void run(){ 

     long lastTime = System.nanoTime(); 
     final double amountOfTicks = 60D; 
     double ns = 1000000000/amountOfTicks; 
     double delta = 0; 

     //init(); 

     while(running){ 
      long now = System.nanoTime(); 
      delta += (now - lastTime)/ns; 
      lastTime = now; 
      if(delta >= 1){ 
       tick(); 
       delta--; 
      } 

      render(); 
     } 
    } 

    private static void init(){ 
     clickers.add(new AutoClicker("Mouse", .1, 10)); 
//  clickers.add(new AutoClicker("Monkey", .36, 50)); 
//  clickers.add(new AutoClicker("Toddler", .5, 250)); 
//  clickers.add(new AutoClicker("Pre-Teen", 1, 700)); 
//  clickers.add(new AutoClicker("Angsty Teen", 1.5, 1500)); 
//  clickers.add(new AutoClicker("Intern", 2.5, 2000)); 
//  clickers.add(new AutoClicker("Newbie", 5, 4000)); 
//  clickers.add(new AutoClicker("HR Staffer", 10, 10000)); 
//  clickers.add(new AutoClicker("Misc. Staffer", 15, 12000)); 
//  clickers.add(new AutoClicker("Media Analyst", 30, 100000)); 
//  clickers.add(new AutoClicker("CEO", 50, 800000)); 
//  clickers.add(new AutoClicker("Researcher", 80, 2000000)); 
//  
//  
//  clickers.add(new AutoClicker("Sacrifice Leader", 500, 99999999)); 

     System.out.println("clickers.size()=\t" + clickers.size()); 

     frameMain.setVisible(true); 

     frameMain.setSize(800, 600); 
     frameMain.setResizable(false); 
     frameMain.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frameMain.setLayout(new FlowLayout()); 


     frameMain.add(buttonMain); 
     buttonMain.addActionListener(new buttonMainAction()); 


     buttonAuto.add(new JButton("0 Mouse(s) - Cost: 10 Clicks")); 
//  buttonAuto.add(new JButton("0 Monkey(s) - Cost: 50 Clicks")); 
//  buttonAuto.add(new JButton("0 Toddler(s) - Cost: 250 Clicks")); 
//  buttonAuto.add(new JButton("0 Pre-Teen(s) - Cost: 700 Clicks")); 
//  buttonAuto.add(new JButton("0 Angsty Teen(s) - Cost: 1500 Clicks")); 
//  buttonAuto.add(new JButton("0 Intern(s) - Cost: 2000 Clicks")); 
//  buttonAuto.add(new JButton("0 Newbie(s) - Cost: 4000 Clicks")); 
//  buttonAuto.add(new JButton("0 HR Staffer(s) - Cost: 10000 Clicks")); 
//  buttonAuto.add(new JButton("0 Misc. Staffer(s) - Cost: 12000 Clicks")); 
//  buttonAuto.add(new JButton("0 Media Analyst(s) - Cost: 100000 Clicks")); 
//  buttonAuto.add(new JButton("0 CEO(s) - Cost: 800000 Clicks")); 
//  buttonAuto.add(new JButton("0 Researcher(s) - Cost: 2000000 Clicks")); 
//  buttonAuto.add(new JButton("0 Sacrafice Leader(s) - Cost: 99999999 Clicks")); 

     frameMain.add(labelcps); 
     frameMain.add(labelCount); 

     for(int i = 0; i<buttonAuto.size(); i++){ 
      buttonAuto.get(i).addActionListener(new buttonBuyAction()); 
     buttonAuto.get(i).setActionCommand(Integer.toString(i)); 
     frameMain.add(buttonAuto.get(i)); 
     } 


     running = true; 
    } 

    /* 
    public synchronized void start(){ 
     if(running) 
      return; 
     running = true; 
     thread = new Thread(this); 
     thread.start(); 
    } 

    public synchronized void stop(){ 
     if(!running) 
      return; 
     running = false; 

     try { 
      thread.join(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
    */ 

    static void tick(){ 
     //do stuff 
     for(AutoClicker clicker: clickers){ 
      clickCount += (clicker.getCPS()/60)* clicker.getNumberOwned(); 
      System.out.println("added " + (clicker.getCPS()/60)* clicker.getNumberOwned() 
        + " from " + clicker.getNumberOwned() + " " + clicker.getName() +"'s"); 
     } 
    } 
    static void render(){ 
     double cpst = 0; 
     for(AutoClicker clicker: clickers){ 
      cpst += (clicker.getCPS())* clicker.getNumberOwned(); 
     } 
     labelCount.setText("[ Click Count: " + (int)clickCount + " ]"); 
     labelcps.setText("[ Click Per Second: " + ((int)(cpst*10))/10.0 + " ]"); 

     for(int i = 0; i < clickers.size(); i++){ 
      if((int)clickers.get(i).getCost()>clickCount){ 
       if(buttonAuto.get(i).isEnabled()) 
        buttonAuto.get(i).setEnabled(false); 
      }else{ 
       if(!buttonAuto.get(i).isEnabled()) 
        buttonAuto.get(i).setEnabled(true); 
      } 

     } 
    } 

} 

А вот мой Автокликеры класс:

public class AutoClicker { 
    private static String name; 
    private static double cps; 
    private static double cost; 
    private static int numberOwned; 

    public AutoClicker(String nameIn, double cpsIn, int costIn){ 
     name = nameIn; 
     cps = cpsIn; 
     cost = costIn; 
     numberOwned = 0; 
    } 

    public String getName(){ 
     return name; 
    } 
    public double getCPS(){ 
     return cps; 
    } 
    public double getCost(){ 
     return cost; 
    } 
    public int getNumberOwned(){ 
     return numberOwned; 
    } 

    public void buy(){ 
     numberOwned++; 
     cost*=1.174; 
    } 
} 

Огромное спасибо!^_^

+1

Вы изменяете состояние пользовательского интерфейса вне контекста EDT, это приведет вас к опасному пути условий гонки нитей, поскольку ваш цикл обновления конкурирует с движком пассивного рендеринга Swing. См. [Параллельность в Swing] (http://docs.oracle.com/javase/tutorial/uiswing/concurrency/) для получения более подробной информации. – MadProgrammer

ответ

5
  1. Избавьтесь от большинства ваших статических модификаторов. Особенно в классе AutoClicker. Когда эти поля статичны, они становятся полями класса, а не объектом, поэтому каждый объект AutoClicker имеет одно и то же поле со всеми остальными - не то, что вы хотите.

Фактически, вероятно, единственное, что должно быть статичным, должно быть основным методом, и все. Тогда вы можете изменить это:

public static void main(String[] args){ 
    init(); 
    run(); 
} 

к этому:

public static void main(String[] args){ 
    Main main = new Main(); 
    main.init(); 
    main.run(); 
} 

Также

  • Вы объявили переменную CP дважды, один в качестве поля класса и один локально к методу render(), и этот последний теняет поле класса - вы уверены, что хотите это сделать?
  • Как указано в комментарии, вы вызываете код в методе run() в основном потоке. Если ваш код был запущен соответствующим образом, это будет вызвано в потоке событий Swing и полностью заморозит вашу программу. Если вы затем исправили это и поместили Runnable в Thread и назвали его start(), теперь вы будете мутировать компоненты Swing из фонового потока - все опасные вещи. Пожалуйста, прочитайте: Урок: Параллельность в Swing, чтобы узнать, как это исправить.
+0

Я проголосовал за «все» – MadProgrammer

+1

@MadProgrammer: все, кроме основного метода. Поздравляем с достижением 200 000, BTW. –

+0

Да, хорошо, если нам нужно;) (и спасибо) – MadProgrammer

Смежные вопросы