3

I've been taking AP Computer Science this year as a sophomore in high school and we mainly cover material like loops, classes, methods, general CS logic, and some math stuff. I am missing what I really loved about coding in the first place, making games. Now every game I have made had some sort of way to manage it whether it was using timers in visual basic or a XNA plugin for c# that setup a update method for me. The problem is I have not learned how to do this for java in my course. I've read up a little on threads and implements runnable but i'm not really sure where I'm going with it.

Class 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;
    }

Class 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);
    }

}

In this instance what I want to happen is, I want a picture that starts in the top to slowly move down smoothly to the bottom. How would i do this?

M.Sameer
  • 3,072
  • 1
  • 24
  • 37
JGerulskis
  • 800
  • 2
  • 10
  • 24

2 Answers2

3

Suggestions:

  • Again, a Swing Timer works well for simple Swing animations or simple game loops. It may not be the greatest choice for complex or rigorous tame loops as its timing is not precise.
  • Most game loops will not be absolutely precise with time slices
  • And so your game model should take this into consideration and should note absolute time slices and use that information in its physics engine or animation.
  • If you must use background threading, do take care that most all Swing calls are made on the Swing event thread. To do otherwise will invite pernicious infrequent and difficult to debug program-ending exceptions. For more details on this, please read Concurrency in Swing.
  • I avoid using null layouts, except when animating components, as this will allow my animation engine to place the component absolutely.
  • When posting code here for us to test, it's best to avoid code that uses local images. Either have the code use an image easily available to all as a URL or create your own image in your code (see below for a simple example).
  • Your compiler should be complaining to you about your using deprecated methods, such as bounds(...), and more importantly, you should heed those complaints as they're there for a reason and suggest increased risk and danger if you use them. So don't use those methods, but instead check the Java API for better substitutes.
  • Just my own personal pet peeve -- please indicate that you've at least read our comments. No one likes putting effort and consideration into trying to help, only to be ignored. I almost didn't post this answer because of this.

For example:

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();
         }
      });
   }

}
Hovercraft Full Of Eels
  • 283,665
  • 25
  • 256
  • 373
1

What I always use is an infinite loop that calls an update method each iteration, in that method, you would do whatever was required to update the state of the game or render a GUI.

Example

public static void main(String[] args){

    // Initialise game

    while(true){
        updateGame();
    }

}

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

What I also do ,which is a little more complex, is create and interface called IUpdateListener and have certain classes that are specialised for a certain element of the game. I would example have an InputListener, an AIListener, each handling a certain element of game updating.

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
    }
}
SamTebbs33
  • 5,507
  • 3
  • 22
  • 44
  • I just learned about infinite loops and the one thing my teacher told us was to avoid them because they cause logic errors! I now see how useful that could be. I was unaware of this because in past languages I used these inf loops wouldn't even compile – JGerulskis Oct 19 '14 at 15:57
  • But now how would you go about making that while loop execute x amount of times in 1 sec – JGerulskis Oct 19 '14 at 15:57
  • @JGerulskis you would have to set a variable to `System.getTimeMillis()`, check how much time the `for` loop used and use `Thread.sleep()` to wait the necessary amount of time. – SamTebbs33 Oct 19 '14 at 16:00
  • @JGerulskis: the above code does not take respect Swing threading responsibilities. Again, consider using a Swing Timer, or if you use your own game loop in a background thread, you **must** take care that all Swing calls are queued on to the Swing event thread. I also re-iterate my 2nd comment above (neither of which you've commented on yet), about avoiding deprecated methods. – Hovercraft Full Of Eels Oct 19 '14 at 16:01