简体   繁体   中英

How can I make image appear randomly every x seconds in java using timer?

I'm working on a game in which I need to 'hit' a mouse/rat, it will disappear and you'll get 1 point. I made it randomly appear everytime i start the app, but I want the image te be drawn randomly every x seconds using Timer() or something.

My code for the game screen looks like this:

import java.awt.Color;
import java.awt.Cursor;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JPanel;
import javax.swing.JTextField;

public class Gamevenster extends JPanel implements Runnable {
        public String Gamestatus = "active";
        private Thread thread;
        //public Main game;

    public int random(int min, int max) {
         int range = (max - min) + 1;     
        return (int)(Math.random() * range) + min;
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        g.drawImage(achtergrond, 0, 0, this.getWidth(), this.getHeight(), null);
        //g.drawImage(muisje, 10, 10, null);
        g.drawImage(muisje, random(0, this.getWidth()), random(0, this.getHeight()), null);
    }

    private static final long serialVersionUID = 1L;

        Image achtergrond, muisje;
        JTextField invoer;
        JButton raden;
        JButton menu;

        Gamevenster() {
        setLayout(null);

        ImageIcon icon = new ImageIcon(this.getClass().getResource("assets/achtergrondspel.png"));
        achtergrond = icon.getImage();      

        ImageIcon icon2 = new ImageIcon(this.getClass().getResource("assets/muisje.png"));
        muisje = icon2.getImage();   

        //Get the default toolkit  
        Toolkit toolkit = Toolkit.getDefaultToolkit();  

        //Load an image for the cursor  
        Image image = toolkit.getImage("src/assets/hand.png");  

        //Create the hotspot for the cursor  
        Point hotSpot = new Point(0,0);

        //Create the custom cursor  
        Cursor cursor = toolkit.createCustomCursor(image, hotSpot, "Hand");

        //Use the custom cursor  
        setCursor(cursor);

        // setLayout( null );

        // Invoer feld
        invoer = new JTextField(10);
        invoer.setLayout(null);
        invoer.setBounds(150, 474, 290, 60); // Verander positie onder aan scherm is int 1

        // Button voor raden
        raden = new JButton("Raden");
        raden.setLayout(null);
        raden.setBounds(10, 474, 130, 60);
        raden.setFont(new Font("Dialog", 1, 20));
        raden.setForeground(Color.white);
        raden.setBackground(new Color(46, 204, 113));
        raden.setPreferredSize(new Dimension(130, 60));

        // Menu knop
        menu = new JButton("Menu");
        menu.setLayout(null);
        menu.setBounds(450, 474, 130, 60);
        menu.setFont(new Font("Dialog", 1, 20));
        menu.setForeground(Color.white);
        menu.setBackground(new Color(46, 204, 113));
        menu.setPreferredSize(new Dimension(130, 60));

        // Toevoegen aan screen
        add(invoer);
        //add(raden);
        add(menu);

        menu.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {
        String i = invoer.getText();
        System.out.println("Er is gedrukt! " + i);
                }
            });
        }

        public void start(){
            thread = new Thread(this,"spelloop");
            thread.start();
        }

        public void run() {
            // TODO Auto-generated method stub
            while(Gamestatus=="active"){
                System.out.println("Gameloop werkt");
            }
        }
}

as you can see I'm using g.drawImage(muisje, random(0, this.getWidth()), random(0, this.getHeight()), null);

So it randomly add the image on startup.

How can I use a timer to do this every x seconds when the app is openend?

"How can I use a timer to do this every x seconds when the app is openend?"

Have a look at this example. I gathered Images from the internet, but you can do the same using image files. What I did was use an array of URL and BufferedImage and got a random index ever 500 milliseconds and repaint() the panel

Note If you are going to use image files, you may want to look at this answer also.

在此输入图像描述

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestImageRotate {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                JFrame frame = new JFrame("Image Timer");
                frame.add(new ImagePanel());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private static class ImagePanel extends JPanel {

        URL[] urls;
        BufferedImage[] images;
        Random rand = new Random();

        public ImagePanel() {
            urls = new URL[5];
            try {
                urls[0] = new URL("http://www.atomicframework.com/assetsY/img/stackoverflow_chicklet.png");
                urls[1] = new URL("http://www.iconsdb.com/icons/download/orange/stackoverflow-256.png");
                urls[2] = new URL("http://img.1mobile.com/market/screenshot/50/com.dd.stackoverflow/0.png");
                urls[3] = new URL("http://www.iconsdb.com/icons/download/orange/stackoverflow-4-512.png");
                urls[4] = new URL("http://www.iconsdb.com/icons/preview/light-gray/stackoverflow-xxl.png");

                images = new BufferedImage[5];
                images[0] = ImageIO.read(urls[0]);
                images[1] = ImageIO.read(urls[1]);
                images[2] = ImageIO.read(urls[2]);
                images[3] = ImageIO.read(urls[3]);
                images[4] = ImageIO.read(urls[4]);

            } catch (MalformedURLException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            setBackground(Color.BLACK);

            Timer timer = new Timer(500, new ActionListener(){
                @Override
                public void actionPerformed(ActionEvent e) {
                    repaint();
                }
            });
            timer.start();
        }

        private int random() {
            int index = rand.nextInt(5);
            return index;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            BufferedImage img = images[random()];
            g.drawImage(img, 0, 0, 400, 400, 0, 0,
                    img.getWidth(), img.getHeight(), this);
        }

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

Notice the Timer code. This is all I did

Timer timer = new Timer(500, new ActionListener(){
    @Override
    public void actionPerformed(ActionEvent e) {
        repaint();
    }
});
timer.start();

And for the .grawImage I use a random index from the array of BufferedImages

@Override
protected void paintComponent(Graphics g) {
    super.paintComponent(g);
    BufferedImage img = images[random()];
    g.drawImage(img, 0, 0, 400, 400, 0, 0,
                           img.getWidth(), img.getHeight(), this);
}

UPDATE Example. I shut down my IDE for the night. Too lazy to open so I'm just going to come up with this as I go. If you still don't it, I'll add a real example tomorrow when I get up.

Basically you want to have global variable for the x and y locations of the mouse image

int x = 0;
int y = 0;

When you draw the image, you want to use these locations

g.drawImage(img, x, y, whatEverWidth, whatEverHeight, this);

In the timer, you can modify the x and y randomly before you paint. Let use some logic.

Let say your scree width is 500 and screen height is 500 and mouse image width is 100 and mouse image height is 100

  • So the max x location will be 400 = screen width - mouse image width
  • And max y location will be 400 = screen height - mouse image height

So now we have our ranges. We know min x location is 0 and min y location is 0. So we want a random number from 0 to 400 for each x and y. So in the timer you can do

Timer timer = new Timer(1000, new ActionListener(){
    public void actionPerformed(ActionEvent e) {
        x = rand.nextInt(400) + 1;     
        y = rand.nextInt(400) + 1;
        repaint();   
    }
});

This will repaint your mouse image at a random location every time repaint is called.


UPDATE 2

I don't know what else is there to explain. I did just those things I pointed out(with my original code), just added an x and y and used them to draw the image, and got a random location in the timer . It's works perfectly fine for me. I don't know what you're doing wrong.

在此输入图像描述

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Random;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;

public class TestImageRotate {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable(){
            @Override
            public void run() {
                JFrame frame = new JFrame("Image Timer");
                frame.add(new ImagePanel());
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    private static class ImagePanel extends JPanel {

        URL[] urls;
        BufferedImage[] images;
        Random rand = new Random();
        private int x = 0;
        private int y = 0;

        public ImagePanel() {
            urls = new URL[5];
            try {
                urls[0] = new URL("http://www.atomicframework.com/assetsY/img/stackoverflow_chicklet.png");
                urls[1] = new URL("http://www.iconsdb.com/icons/download/orange/stackoverflow-256.png");
                urls[2] = new URL("http://img.1mobile.com/market/screenshot/50/com.dd.stackoverflow/0.png");
                urls[3] = new URL("http://www.iconsdb.com/icons/download/orange/stackoverflow-4-512.png");
                urls[4] = new URL("http://www.iconsdb.com/icons/preview/light-gray/stackoverflow-xxl.png");

                images = new BufferedImage[5];
                images[0] = ImageIO.read(urls[0]);
                images[1] = ImageIO.read(urls[1]);
                images[2] = ImageIO.read(urls[2]);
                images[3] = ImageIO.read(urls[3]);
                images[4] = ImageIO.read(urls[4]);

            } catch (MalformedURLException ex) {
                ex.printStackTrace();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
            setBackground(Color.BLACK);

            Timer timer = new Timer(500, new ActionListener(){
                @Override
                public void actionPerformed(ActionEvent e) {
                    x = rand.nextInt(325);
                    y = rand.nextInt(325);
                    repaint();
                }
            });
            timer.start();
        }

        private int random() {
            int index = rand.nextInt(5);
            return index;
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            BufferedImage img = images[random()];
            g.drawImage(img, x, y, 75, 75, this);
        }

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

Well i am a beginner too. So if i misguide you i am sorry in advance. Thats my first answer. What you are looking for is probably this
System.currentTimeMillis();
this will give the current time as milisecs. So You will probably want to use another float to calculate passed time and lets name it deltaTime. You can find deltaTime by deltaTime=System.currentTimeMillis(); use this before while loop in run method. Then inside the loop, if System.currentTimeMillis()-deltaTime is bigger than x number(miliseconds), spawn a rat. And reset deltaTime.

And I see you didn't declared ax,y position integer to store rats x and y location. So declare 2 global variables for x and y of rats. if rats multiple that x and y int should be arrays with enough room to keep all your rats positions.

Make an method so every time a rat spawns, x and y of rat's location gets a random int. You actually figured it out in graphics section. But random function shouldn't be in there. Instead of random function x and y integers should be there. In your code it will randomize location of rat everytime it updates graphics. No that's not what you want (probably).

One more thing, your code actually won't work without update method called. You should put update(); at the end of your while loop.

Sorry if i am mistaken or not clear enough. I am only a beginner interested in the same topics before.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM