你的位置:首页 > Java教程

[Java教程]JAVA小项目之摇奖机


  功能:

  1. 点击”摇杆“开始;
  2. 两种结束滚动方式,A:点击”摇杆“ B:分别点击 对应结果框的按钮;
  3. 实现最后减速停下来效果,模拟真实摇奖机。

  知识点:A.线程的控制,B.图片轮播原理

效果图:

  "为什么传不了图片?"

  • 窗口类
 1 package com.gxlee.lhj; 2  3 import java.awt.Color; 4 import java.awt.Container; 5 import java.awt.Graphics; 6 import java.awt.event.MouseAdapter; 7 import java.awt.event.MouseEvent; 8 import java.awt.image.BufferedImage; 9 import java.util.ArrayList; 10 import java.util.List; 11 import java.util.Random; 12  13 import javax.swing.JFrame; 14 import javax.swing.JPanel; 15  16 @SuppressWarnings("serial") 17 public class MainFrame extends JFrame { 18  19   private List<Fruit> fruits; 20   private boolean running = false; 21   private Random r = new Random(); 22   private String backimg = "bg.png"; 23   private int fruitOver = 0; 24  25   public MainFrame() { 26     // 构造函数 27     this.setTitle("摇奖机 v1.0"); 28     this.setSize(Utils.WIDTH, Utils.HEIGHT); 29     this.setDefaultCloseOperation(EXIT_ON_CLOSE); 30     this.setLocationRelativeTo(null); 31     this.setResizable(false); 32  33     Container c = getContentPane(); 34     MyPanel zb = new MyPanel(); 35     c.add(zb); 36     fruits = new ArrayList<Fruit>(); 37     // 添加3个 38     for (int i = 0; i < 3; i++) { 39       Fruit fruit = new Fruit(); 40       fruit.setIndex(r.nextInt(6)); 41       fruits.add(fruit); 42     } 43     this.addMouseListener(new MousClick()); 44     this.setVisible(true); 45  46   } 47  48   public class MyPanel extends JPanel { 49  50     protected void paintComponent(Graphics g) { 51       g.fillRect(0, 0, Utils.WIDTH, Utils.HEIGHT); 52       g.drawImage(Utils.images.get(backimg), 0, 0, Utils.WIDTH, 53           Utils.HEIGHT, this); 54       BufferedImage image = Utils.images.get("fruit.jpg"); 55       BufferedImage subImg = null; 56  57       // 画水果 58       if (!running && fruitOver == 3) { 59         int i = 0; 60         for (Fruit f : fruits) { 61           subImg = image.getSubimage(f.getIndex() * 94, 0, 94, 102); 62           g.drawImage(subImg, 84 + (i++ * (67 + 9)), 313, 67, 100, 63               this); 64         } 65       } else { 66         int i = 0; 67         for (Fruit f : fruits) { 68           int index = f.getIndex(); 69           int offset = f.getOffset(); 70           int nextIndex = 0; 71           // 如果offset == 0 的话 或者已经移动到 就只需要一张 72           if (!f.isAlive() || offset == 0) { 73             subImg = image.getSubimage(f.getIndex() * 94, 0, 94, 74                 102); 75             g.drawImage(subImg, 84 + ((i) * (67 + 9)), 313, 67, 100, 76                 this); 77             i+=1; 78             continue; 79           } 80           // 得到下一张图的index 81           nextIndex = (index == 5) ? 0 : index + 1; 82           // 画第一张 83           subImg = image.getSubimage(index * 94, 0, 94, 102 - offset); 84           g.drawImage(subImg, 84 + (i * (67 + 9)), 313 + offset, 67, 85               100 - offset, this); 86           // 画第二张 87           subImg = image.getSubimage(nextIndex * 94, 102 - offset, 88               94, offset);// 取得子图标 89           g.drawImage(subImg, 84 + (i * (67 + 9)), 313, 67, offset, 90               this); 91           i+=1; 92         } 93       } 94       g.setColor(new Color(181, 36, 43)); 95       g.fillRect(84, 358, 220, 6); 96     } 97   } 98  99   public class MousClick extends MouseAdapter {100 101     @Override102     public void mouseClicked(MouseEvent e) {103       int x = e.getX();104       int y = e.getY();105       //如果按的是开始摇杆106       if(x<=415 && x>=371){107         if(y<=200 && y>=160){108           running = true ^ running;109           new ShowBackGroud().start();110           if(running){111             fruitOver = 0;112             fruits.clear();113             for (int i = 0; i < 3; i++) {114               Fruit f = new Fruit();115               f.setIndex(r.nextInt(6));116               f.setRunning(true);117               fruits.add(f);118               new MyThread(f, 70 + i * 10).start();119               f.setAlive(true);120             }121           }else{122             for (Fruit f : fruits) {123               f.setRunning(false);124             }125           }126         }127         return;128       }129       int index = -1;130       if(y<=495 && y>=480){131         if(x>=60 && x<=90){132           //第一个按钮133           index = 0;134         }else if(x>=106 && x<=140){135           //第二个按钮136           index = 1;137         }else if(x>=153 && x<=182){138           //第三个按钮139           index = 2;140         }141         if(running && index >-1)142           fruits.get(index).setRunning(false);143       }144     }145   }146 147   public static void main(String[] args) {148     new MainFrame();149   }150 151   public class MyThread extends Thread {152     public Fruit f;153     public int speed;//最后慢下来时候的初始速度154     public int sleep = 40;//休眠时长155     public int offset;//当传递一个速度是 要完成N张图片的正好播放完产生一个偏移位置156     public MyThread(Fruit f, int delay) {157       this.f = f;158       this.speed = delay;159       offset = getOffset(delay);160       161     }162     public int getOffset(int delay){163       int sum = 0;164       for(int i = 1;i<=delay;i++){165         sum +=i;166       }167       return sum % 102;168     }169     @Override170     public void run() {171       while (f.isRunning()) {172         f.setSpeed(90);// r.nextInt(70)+10 区别不大173         try {174           Thread.sleep(40);175         } catch (InterruptedException e) {176         }177         repaint();178       }179       // 停止的时候180       //修正距离 从速度N开始减 速度每减1 181       //70开始的话 能走 2485:2485%102 = 37182       // 80的话 3240%102= 78 90%4095%102=15 183       f.setDistance(offset, true);//留一个像素184       int sum = 0;185       while (f.isAlive()) {186         //缓慢下来的效果187         f.setSpeed(speed);188         sum += speed;189         speed-- ;190         try {191           Thread.sleep(sleep+=3);192         } catch (InterruptedException e) {193         }194         repaint();195       }196       synchronized (new Object()) {197         fruitOver++;198       }199     }200 201   }202 203   public class ShowBackGroud extends Thread {204 205     @Override206     public void run() {207       backimg = "bg2.png";208       try {209         Thread.sleep(500);210       } catch (InterruptedException e) {211       }212       backimg = "bg.png";213     }214 215   }216 217 }

View Code
  • 水果类
 1 package com.gxlee.lhj; 2  3  4 public class Fruit { 5   private int index = 0; 6   private int nextIndex = 0; 7   private int maxIndex = 5; 8   private int width=94 ;//单个图片的宽度 并 9   private int height = 102;//图片的高度 后面并没有用到 全部写死10   private int distance;11   private boolean alive = true;12   private boolean running ;13   private int speed;14   private int offset;15   public void setSpeed(int speed){16     if (speed<=0){17       speed = 0;18       alive = false;19     }20     this.speed = speed;21     setDisttance(distance+= speed);22   }23   24   public boolean isRunning() {25     return running;26   }27 28   public void setRunning(boolean running) {29     this.running = running;30   }31 32   public int getNextIndex() {33     return nextIndex;34   }35   public void setNextIndex(int nextIndex) {36     this.nextIndex = nextIndex;37   }38   public int getOffset() {39     return offset;40   }41   public void setOffset(int offset) {42     this.offset = offset;43   }44 45   public int getSpeed() {46     return speed;47   }48   public boolean isAlive() {49     return alive;50   }51 52   public void setAlive(boolean alive) {53     this.alive = alive;54   }55 56   public int getDistance() {57     return distance;58   }59   public void setDistance(int offset, boolean flag ) {60     int nextIndex = index==5?0:index+1;61     int dis = nextIndex*102+102-(offset);62     setDisttance(dis);63   }64   public void setDisttance(int distance){65     if(distance>=6*102){distance = distance % 102;}66     this.distance = distance; 67     index = distance / 102;68     offset = distance % 102;69     nextIndex = (index == 5) ? 0 : index + 1;  70   }71 72   public void setIndex(int index){73     this.index = index;74     distance = index*height;75   }76   77   public int getHeight(){78     return height;79   }80   public int getIndex() {81     return index;82   }83 84   public int getMaxIndex() {85     return maxIndex;86   }87   public void setMaxIndex(int maxIndex) {88     this.maxIndex = maxIndex;89   }90   public int getWidth() {91     return width;92   }93   94   95   96 }

View Code
  • 工具类
 1 package com.gxlee.lhj; 2  3 import java.awt.image.BufferedImage; 4 import java.io.File; 5 import java.io.IOException; 6 import java.util.HashMap; 7 import java.util.Map; 8  9 import javax.imageio.ImageIO;10 11 public class Utils {12   public static Map<String, BufferedImage> images = new HashMap<String,BufferedImage>();13   public static final int WIDTH = 440;14   public static final int HEIGHT =600;15   16   public static final int FRUIT_WIDTH = 94;17   public static final int FRUIT_HEIGHT = 102;18   19   20   static{21    File dir = new File("img");22    File[] files = dir.listFiles();23    for (File file:files) {24     try {25       BufferedImage image = ImageIO.read(file);26       images.put(file.getName(), image);27     } catch (IOException e) {28       //e.printStackTrace();29     }30   }  31   }32 }

View Code

素材: