创建一个可以不断更新变量的java方法

时间:2014-10-19 15:43:38

标签: java swing animation

我今年作为高中二年级学习AP计算机科学,我们主要涵盖循环,课程,方法,一般CS逻辑和一些数学等材料。我很想念我最喜欢的编码,制作游戏。现在我制作的每个游戏都有某种方式来管理它,无论是在visual basic中使用计时器还是在c#中为我设置更新方法的XNA插件。问题是我在课程中还没有学会如何为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 个答案:

答案 0 :(得分: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();
         }
      });
   }

}

答案 1 :(得分:1)

我一直使用的是一个无限循环,每次迭代都会调用一个更新方法,在那个方法中,你可以做任何更新游戏状态或渲染GUI所需的东西。

实施例

public static void main(String[] args){

    // Initialise game

    while(true){
        updateGame();
    }

}

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

我也做了,这有点复杂,是名为IUpdateListener的创建和界面,并且有一些专门用于游戏某个元素的类。我的例子是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
    }
}