功能:
- 点击”摇杆“开始;
- 两种结束滚动方式,A:点击”摇杆“ B:分别点击 对应结果框的按钮;
- 实现最后减速停下来效果,模拟真实摇奖机。
知识点: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 Listfruits; 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 (); 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 @Override 102 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 @Override 170 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 = 37 182 // 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 @Override 206 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 }
- 水果类
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 }
- 工具类
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 Mapimages = new HashMap (); 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 }
素材:
- 主界面:
- 水果: