Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package bouncer2;
- /* NOTE: requires MyImage.java */
- import java.awt.BorderLayout;
- import java.awt.Color;
- import java.awt.Dimension;
- import java.awt.Graphics;
- import java.awt.Point;
- import java.awt.event.ActionEvent;
- import java.awt.event.ActionListener;
- import java.util.ArrayList;
- import javax.swing.JButton;
- import javax.swing.JFrame;
- import javax.swing.JPanel;
- public class BouncingImages2 extends JFrame implements ActionListener {
- public static void main(String[] args) {
- new BouncingImages2();
- }
- /* These are the width and height of the DrawingPanel NOT the whole JFrame.
- Bouncing off walls will not work properly if it's the JFrame size */
- static final int WINW = 1000;
- static final int WINH = 800;
- static boolean imagesLoaded = true;
- JPanel buttonPanel = new JPanel();
- AnimationPanel animationPanel;
- ArrayList<ImageRect> imageList = new ArrayList<ImageRect>();
- AnimationThread thread;
- private volatile boolean stopRequested = false; //maybe should use AtomicBoolean
- BouncingImages2() {
- //set up button panel
- JButton btnStart = new JButton("Start");
- JButton btnStop = new JButton("Stop");
- JButton btnExit = new JButton("Exit");
- btnStart.addActionListener(this);
- btnStop.addActionListener(this);
- btnExit.addActionListener(this);
- buttonPanel.add(btnStart);
- buttonPanel.add(btnStop);
- buttonPanel.add(btnExit);
- animationPanel = new AnimationPanel();
- //setup JFrame
- //this.setExtendedState(JFrame.MAXIMIZED_BOTH); //If we use this, then we need to determine the dimensions of the JPanel before we start drawing
- // this.setUndecorated(true);
- this.add(buttonPanel, BorderLayout.SOUTH);
- this.add(animationPanel);
- this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- this.pack(); //since the JPanel is controlling the size, we need pack() here.
- this.setLocationRelativeTo(null); //after pack();
- this.setVisible(true);
- }
- void startAnimation() {
- //this doesn't restart the thread if it terminates
- if (thread == null) {
- thread = new AnimationThread ();
- stopRequested = false;
- thread.start();
- }
- //System.out.println("thread is " + thread.toString());
- //this will "restart" the thread!
- if (thread.getThreadGroup() == null) {
- thread = new AnimationThread ();
- stopRequested = false;
- thread.start();
- }
- }
- //two different versions here as I was testing how to stop threads properly
- void stopAnimation1(){
- stopRequested = true;
- }
- void stopAnimation2(){
- thread.interrupt();
- //System.out.println(thread.isInterrupted());
- }
- void addImage() {
- // imageList.add(new ImageRect("planeIcon.png"));
- //don't allow two images to be added on top of each other
- ImageRect ir = null;
- while (true) {
- ir= new ImageRect("planeIcon.pngx");
- if (checkCollision(ir)) {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {}
- } else {
- break;
- }
- }
- imageList.add(ir);
- }
- void moveAllImages() {
- for (ImageRect image : imageList) {
- image.moveImage();
- image.calculatePoints();
- checkCollision(image);
- }
- }
- boolean checkCollision(ImageRect currIm) {
- for (ImageRect im : imageList) {
- if (currIm == im) continue; //don't collide with yourself
- // check to see if the two images are close enough to collide
- // if (distance (currIm.ctr, im.ctr) > (ImageRect.biggestDim*ImageRect.biggestDim*4)) {
- // return; //I think that this should be (1.5 * biggestDim)^2
- // }
- if (currIm.intersects(im)) {
- //determine which side hits
- //first check the centres:
- //Does it hit the left or right side?
- if (im.contains(currIm.ml) || im.contains(currIm.mr)) {
- currIm.undoMove();
- currIm.vx *= -1;
- return true;
- }
- //does it hit the top or bottom?
- if (im.contains(currIm.mt) || im.contains(currIm.mb)) {
- currIm.undoMove();
- currIm.vy *= -1;
- return true;
- }
- //We have to reverse this too because a large rectangle can move over a small one and freeze if the small one fits between the corner and a midpoint
- if (currIm.contains(im.ml) || currIm.contains(im.mr)) {
- currIm.undoMove();
- currIm.vx *= -1;
- return true;
- }
- //does it hit the top or bottom?
- if (currIm.contains(im.mt) || currIm.contains(im.mb)) {
- currIm.undoMove();
- currIm.vy *= -1;
- return true;
- }
- //does it hit a corner? This part has the least realistic bounce
- if (im.contains(currIm.tl) || im.contains(currIm.tr) || im.contains(currIm.bl) || im.contains(currIm.br)) {
- currIm.undoMove();
- currIm.vx *= -1;
- currIm.vy *= -1;
- return true;
- }
- }
- }
- return false;
- }
- //for sake of speed, it returns distance squared
- int distance(Point p1, Point p2) {
- int dx = p1.x-p2.x;
- int dy = p1.y-p2.y;
- return dx*dx+dy*dy;
- }
- //ActionListener for Buttons
- @Override
- public void actionPerformed(ActionEvent e) {
- if (e.getActionCommand().equals("Start")) {
- addImage();
- startAnimation();
- }
- if (e.getActionCommand().equals("Stop")) {
- stopAnimation2();
- }
- if (e.getActionCommand().equals("Exit")) {
- System.exit(0);
- }
- }
- //This class does drawing graphics and nothing else
- class AnimationPanel extends JPanel {
- AnimationPanel() {
- this.setBackground(new Color(222,222,255));
- this.setPreferredSize(new Dimension(WINW, WINH));
- }
- @Override
- public void paintComponent(Graphics g){
- synchronized(g) { //try to stop flicker
- super.paintComponent(g);
- g.setColor(Color.ORANGE);
- for (ImageRect im : imageList) {
- if(imagesLoaded) {
- g.drawImage(im.image, im.x, im.y, im.width, im.height,null);
- g.drawRect(im.x, im.y, im.width, im.height);
- } else {
- g.setColor(im.color);
- g.fillRect(im.x, im.y, im.width, im.height);
- }
- }
- }
- }
- }
- /* NOTE: I'm not that experienced with threads, preferring to use timers. A Swing Timer would work perfectly for this program
- * Quote: "Starting from Java 5 it is not a good idea to work with Threads directly.
- * You should rather use Executor framework and choose an execution policy depending on your requirements."
- */
- private class AnimationThread extends Thread {
- public void run() {
- run2B(); //here we can test different methods
- }
- //this version stops the thread using a flag and break. (use stopAnimation1())
- public void run1() {
- while (true) {
- //everything in the main game loop goes here
- moveAllImages();
- // animationPanel.repaint();
- animationPanel.paintImmediately(0, 0, WINW, WINH);
- try {
- this.sleep(5);
- } catch (InterruptedException e) {}
- if(stopRequested) break;
- }
- }
- //this version stops the thread using an interrupt and break (use stopAnimation2())
- public void run2A() {
- while (true) {
- moveAllImages();
- //collide_images()
- animationPanel.repaint();
- try {
- this.sleep(5);
- } catch (InterruptedException e) {
- System.out.println("interrupted");
- break;
- }
- }
- }
- //this version stops the thread using interrupt only (use stopAnimation2())
- public void run2B() {
- while ( ! thread.isInterrupted() ) { // or //while (! Thread.currentThread().isInterrupted() ) {
- moveAllImages();
- //collide_images()
- animationPanel.repaint();
- try {
- this.sleep(5);
- } catch (InterruptedException e) {
- System.out.println("interrupted");
- thread.interrupt(); //catching the exception seems to clear it.
- }
- }
- }
- }
- }
Add Comment
Please, Sign In to add comment