2014-10-19 88 views
2

我今年已經在AP計算機科學大學二年級學習,主要講述循環,類,方法,一般CS邏輯和一些數學方面的內容。我錯過了我最喜歡編碼的東西,製作遊戲。現在我所做的每一個遊戲都有一些方法來管理它,無論是使用visual basic的定時器還是使用c#的XNA插件來爲我設置更新方法。問題是我沒有在我的課程中學會如何爲java做這件事。我已經讀過一些線程和實現可運行的,但我不確定我要去哪裏。創建一個可以連續更新變量的java方法

1級

import java.awt.FlowLayout; 
    import javax.swing.ImageIcon; 
    import javax.swing.JFrame; 
    import javax.swing.JLabel; 

    public class GFXScreen extends JFrame 
    { 
     /** 
     * @param screenHeigth 
     * @param screenHeigth 
     * @param The file name of the image. Make sure to include the extension type also 
     * @param The title at the top of the running screen 
     * @param The height of the screen 
     * @param The width of the screen 
     */ 
     public GFXScreen(String fileName, String screenTitle, int screenHeight, int screenWidth) 
     { 
      setLayout(new FlowLayout()); 

      image1 = new ImageIcon(getClass().getResource(fileName)); 
      label1 = new JLabel(image1); 
      this.add(label1); 

      //Set up JFrame 
      this.setDefaultCloseOperation(EXIT_ON_CLOSE); 
      this.setVisible(true); 
      this.setTitle(screenTitle); 
      this.setSize(screenWidth, screenHeight); 

     } 

     /** 
     * @param desired amount to move picture 
     */ 
     public void updatePic(int increment) 
     { 
      //update pos 
      label1.setBounds(label1.bounds().x, label1.bounds().y - increment, 
        label1.bounds().width, label1.bounds().height); 
     } 

     private ImageIcon image1; 
     private JLabel label1; 
    } 

2級

public class MainClass implements Runnable { 

    public static void main(String[] args) 
    { 
     (new Thread(new MainClass())).start(); 
     GFXScreen gfx = new GFXScreen("pixel_man.png", "pixel_Man", 1000, 1000); 

    } 

    public void run() 
    { 
     gfx.updatePic(1); 
    } 

} 

在這種情況下我希望發生的事情是,我想要開始在頂部的畫面慢慢平穩向下移動至底部。我將如何做到這一點?

+2

擺動計時器會爲這項工作做得很好。 – 2014-10-19 15:44:47

+1

[例如](http://stackoverflow.com/a/12545773/522444)。 – 2014-10-19 15:46:29

+1

此外,您的編譯器應該向您抱怨您使用的已棄用方法,更重要的是,您應該理解這些抱怨。不要使用這些方法,而是檢查Java API以獲得更好的替代品。 – 2014-10-19 15:48:42

回答

1

我總是使用的是一個無限循環,每次迭代調用更新方法,在該方法中,您將執行任何更新遊戲狀態或呈現GUI所需的操作。

public static void main(String[] args){ 

    // Initialise game 

    while(true){ 
     updateGame(); 
    } 

} 

public static void updateGame(){ 
    // Update things here. 
} 

什麼我也做什麼,這是一個稍微複雜一點,是建立和接口稱爲,並有某些類別的專業是爲遊戲的某個元素。我會舉例InputListenerAIListener,每個處理遊戲更新的某個元素。

public interface IUpdateListener{ 
    public void update(); 
} 


public class Main{ 

    public static ArrayList<IUpdateListener> listeners = new ArrayList<IUpdateListener>(); 

    public static void main(String[] args){ 
     listeners.add(new InputListener()); 
     while(true){ 
      for(IUpdateListener listener : listeners){ 
       listener.update(); 
      } 
     } 
    } 
} 

public class InputListener implements IUpdateListener{ 
    public void update(){ 
     // Handle user input here etc 
    } 
} 
+0

我剛剛瞭解到無限循環,我的老師告訴我們的一件事是避免它們,因爲它們會導致邏輯錯誤!我現在看到這可能是多麼有用。我沒有意識到這一點,因爲在過去的語言中,我使用這些inf循環甚至不會編譯 – JGerulskis 2014-10-19 15:57:18

+0

但是現在如何讓while循環在1秒內執行x次數 – JGerulskis 2014-10-19 15:57:59

+0

@JGerulskis您必須將變量設置爲''System.getTimeMillis()',檢查'for'循環使用多少時間,並使用'Thread.sleep()'等待所需的時間。 – SamTebbs33 2014-10-19 16:00:02

2

建議:

  • 再次,Swing Timer非常適用於簡單的Swing動畫或簡單的遊戲循環。對於複雜或嚴格的馴服循環來說,它可能不是最好的選擇,因爲它的時間不精確。
  • 大多數遊戲循環將不會與時間片絕對精確
  • 所以你的遊戲模型應該考慮到這一點,並應注意絕對時間片,並在其物理引擎或動畫中使用該信息。
  • 如果您必須使用後臺線程,請確保大部分Swing調用都是在Swing事件線程上進行的。否則會導致有害的頻繁而難以調試的程序結束異常。欲瞭解更多詳情,請閱讀Concurrency in Swing
  • 我避免使用null佈局,除了動畫組件時,因爲這將允許我的動畫引擎絕對地放置組件。
  • 在這裏發佈代碼供我們測試時,最好避免使用本地圖像的代碼。要麼代碼使用一個容易獲得的圖像作爲URL或在您的代碼中創建您自己的圖像(請參閱下面的一個簡單示例)。
  • 您的編譯器應該向您抱怨使用了不推薦使用的方法,例如bounds(...),更重要的是,您應該留意這些抱怨,因爲他們出於某種原因,並建議如果您使用它們會增加風險和危險。所以不要使用這些方法,而是檢查Java API以獲得更好的替代品。
  • 只是我自己的私人寵物 - 請指出你至少讀過我們的評論。沒有人願意努力和考慮嘗試幫助,只是被忽視。因爲這個,我幾乎沒有發佈這個答案。

例如:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.Graphics2D; 
import java.awt.Image; 
import java.awt.Point; 
import java.awt.event.ActionEvent; 
import java.awt.event.ActionListener; 
import java.awt.image.BufferedImage; 

import javax.swing.AbstractAction; 
import javax.swing.ImageIcon; 
import javax.swing.JButton; 
import javax.swing.JFrame; 
import javax.swing.JLabel; 
import javax.swing.JPanel; 
import javax.swing.SwingUtilities; 
import javax.swing.Timer; 

@SuppressWarnings("serial") 
public class GfxPanel extends JPanel { 

    private static final int BI_WIDTH = 26; 
    private static final int BI_HEIGHT = BI_WIDTH; 
    private static final int GAP = 6; 
    private static final Point INITIAL_LOCATION = new Point(0, 0); 
    private static final int TIMER_DELAY = 40; 
    public static final int STEP = 1; 
    private ImageIcon image1; 
    private JLabel label1; 
    private Point labelLocation = INITIAL_LOCATION; 
    private int prefW; 
    private int prefH; 
    private Timer timer; 

    public GfxPanel(int width, int height) { 
     // the only time I use null layouts is for component animation. 
     setLayout(null); 
     this.prefW = width; 
     this.prefH = height; 

     // My program creates its image so you can run it without an image file 
     image1 = new ImageIcon(createMyImage()); 
     label1 = new JLabel(image1); 
     label1.setSize(label1.getPreferredSize()); 
     label1.setLocation(labelLocation); 
     this.add(label1); 
    } 

    @Override 
    public Dimension getPreferredSize() { 
     return new Dimension(prefW, prefH); 
    } 

    public void startAnimation() { 
     if (timer != null && timer.isRunning()) { 
     timer.stop(); 
     } 
     labelLocation = INITIAL_LOCATION; 
     timer = new Timer(TIMER_DELAY, new TimerListener()); 
     timer.start(); 
    } 

    // My program creates its image so you can run it without an image file 
    private Image createMyImage() { 
     BufferedImage bi = new BufferedImage(BI_WIDTH, BI_HEIGHT, 
      BufferedImage.TYPE_INT_ARGB); 
     Graphics2D g2 = bi.createGraphics(); 
     g2.setColor(Color.red); 
     g2.fillRect(0, 0, BI_WIDTH, BI_HEIGHT); 
     g2.setColor(Color.blue); 
     int x = GAP; 
     int y = x; 
     int width = BI_WIDTH - 2 * GAP; 
     int height = BI_HEIGHT - 2 * GAP; 
     g2.fillRect(x, y, width, height); 
     g2.dispose(); 
     return bi; 
    } 

    private class TimerListener implements ActionListener { 
     @Override 
     public void actionPerformed(ActionEvent e) { 
     int x = labelLocation.x + STEP; 
     int y = labelLocation.y + STEP; 
     labelLocation = new Point(x, y); 
     label1.setLocation(labelLocation); 
     repaint(); 

     if (x + BI_WIDTH > getWidth() || y + BI_HEIGHT > getHeight()) { 
      System.out.println("Stopping Timer"); 
      ((Timer) e.getSource()).stop(); 
     } 
     } 
    } 

    private static void createAndShowGui() { 
     final GfxPanel gfxPanel = new GfxPanel(900, 750); 

     JButton button = new JButton(new AbstractAction("Animate") { 

     @Override 
     public void actionPerformed(ActionEvent arg0) { 
      gfxPanel.startAnimation(); 
     } 
     }); 
     JPanel buttonPanel = new JPanel(); 
     buttonPanel.add(button); 

     JFrame frame = new JFrame("GFXScreen"); 
     frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); 
     frame.getContentPane().add(gfxPanel); 
     frame.getContentPane().add(buttonPanel, BorderLayout.PAGE_END); 
     frame.pack(); 
     frame.setLocationByPlatform(true); 
     frame.setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 
     public void run() { 
      createAndShowGui(); 
     } 
     }); 
    } 

} 
相關問題