功能:

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

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

效果图:

   

  • 窗口类
 package com.gxlee.lhj;

 import java.awt.Color;
 import java.awt.Container;
 import java.awt.Graphics;
 import java.awt.event.MouseAdapter;
 import java.awt.event.MouseEvent;
 import java.awt.image.BufferedImage;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;

 import javax.swing.JFrame;
 import javax.swing.JPanel;

 @SuppressWarnings("serial")
 public class MainFrame extends JFrame {

     private List<Fruit> fruits;
     private boolean running = false;
     private Random r = new Random();
     private String backimg = "bg.png";
     private int fruitOver = 0;

     public MainFrame() {
         // 构造函数
         this.setTitle("摇奖机  v1.0");
         this.setSize(Utils.WIDTH, Utils.HEIGHT);
         this.setDefaultCloseOperation(EXIT_ON_CLOSE);
         this.setLocationRelativeTo(null);
         this.setResizable(false);

         Container c = getContentPane();
         MyPanel zb = new MyPanel();
         c.add(zb);
         fruits = new ArrayList<Fruit>();
         // 添加3个
         for (int i = 0; i < 3; i++) {
             Fruit fruit = new Fruit();
             fruit.setIndex(r.nextInt(6));
             fruits.add(fruit);
         }
         this.addMouseListener(new MousClick());
         this.setVisible(true);

     }

     public class MyPanel extends JPanel {

         protected void paintComponent(Graphics g) {
             g.fillRect(0, 0, Utils.WIDTH, Utils.HEIGHT);
             g.drawImage(Utils.images.get(backimg), 0, 0, Utils.WIDTH,
                     Utils.HEIGHT, this);
             BufferedImage image = Utils.images.get("fruit.jpg");
             BufferedImage subImg = null;

             // 画水果
             if (!running && fruitOver == 3) {
                 int i = 0;
                 for (Fruit f : fruits) {
                     subImg = image.getSubimage(f.getIndex() * 94, 0, 94, 102);
                     g.drawImage(subImg, 84 + (i++ * (67 + 9)), 313, 67, 100,
                             this);
                 }
             } else {
                 int i = 0;
                 for (Fruit f : fruits) {
                     int index = f.getIndex();
                     int offset = f.getOffset();
                     int nextIndex = 0;
                     // 如果offset == 0 的话 或者已经移动到 就只需要一张
                     if (!f.isAlive() || offset == 0) {
                         subImg = image.getSubimage(f.getIndex() * 94, 0, 94,
                                 102);
                         g.drawImage(subImg, 84 + ((i) * (67 + 9)), 313, 67, 100,
                                 this);
                         i+=1;
                         continue;
                     }
                     // 得到下一张图的index
                     nextIndex = (index == 5) ? 0 : index + 1;
                     // 画第一张
                     subImg = image.getSubimage(index * 94, 0, 94, 102 - offset);
                     g.drawImage(subImg, 84 + (i * (67 + 9)), 313 + offset, 67,
                             100 - offset, this);
                     // 画第二张
                     subImg = image.getSubimage(nextIndex * 94, 102 - offset,
                             94, offset);// 取得子图标
                     g.drawImage(subImg, 84 + (i * (67 + 9)), 313, 67, offset,
                             this);
                     i+=1;
                 }
             }
             g.setColor(new Color(181, 36, 43));
             g.fillRect(84, 358, 220, 6);
         }
     }

     public class MousClick extends MouseAdapter {

         @Override
         public void mouseClicked(MouseEvent e) {
             int x = e.getX();
             int y = e.getY();
             //如果按的是开始摇杆
             if(x<=415 && x>=371){
                 if(y<=200 && y>=160){
                     running = true ^ running;
                     new ShowBackGroud().start();
                     if(running){
                         fruitOver = 0;
                         fruits.clear();
                         for (int i = 0; i < 3; i++) {
                             Fruit f = new Fruit();
                             f.setIndex(r.nextInt(6));
                             f.setRunning(true);
                             fruits.add(f);
                             new MyThread(f, 70 + i * 10).start();
                             f.setAlive(true);
                         }
                     }else{
                         for (Fruit f : fruits) {
                             f.setRunning(false);
                         }
                     }
                 }
                 return;
             }
             int index = -1;
             if(y<=495 && y>=480){
                 if(x>=60 && x<=90){
                     //第一个按钮
                      index = 0;
                 }else if(x>=106 && x<=140){
                     //第二个按钮
                      index = 1;
                 }else if(x>=153 && x<=182){
                     //第三个按钮
                     index = 2;
                 }
                 if(running && index >-1)
                     fruits.get(index).setRunning(false);
             }
         }
     }

     public static void main(String[] args) {
         new MainFrame();
     }

     public class MyThread extends Thread {
         public Fruit f;
         public int speed;//最后慢下来时候的初始速度
         public int sleep = 40;//休眠时长
         public int offset;//当传递一个速度是  要完成N张图片的正好播放完产生一个偏移位置
         public MyThread(Fruit f, int delay) {
             this.f = f;
             this.speed = delay;
             offset = getOffset(delay);

         }
         public int getOffset(int delay){
             int sum = 0;
             for(int i = 1;i<=delay;i++){
                 sum +=i;
             }
             return sum % 102;
         }
         @Override
         public void run() {
             while (f.isRunning()) {
                 f.setSpeed(90);// r.nextInt(70)+10 区别不大
                 try {
                     Thread.sleep(40);
                 } catch (InterruptedException e) {
                 }
                 repaint();
             }
             // 停止的时候
             //修正距离  从速度N开始减 速度每减1
             //70开始的话 能走 2485:2485%102 = 37
             // 80的话 3240%102= 78  90%4095%102=15
             f.setDistance(offset, true);//留一个像素
             int sum = 0;
             while (f.isAlive()) {
                 //缓慢下来的效果
                 f.setSpeed(speed);
                 sum += speed;
                 speed-- ;
                 try {
                     Thread.sleep(sleep+=3);
                 } catch (InterruptedException e) {
                 }
                 repaint();
             }
             synchronized (new Object()) {
                 fruitOver++;
             }
         }

     }

     public class ShowBackGroud extends Thread {

         @Override
         public void run() {
             backimg = "bg2.png";
             try {
                 Thread.sleep(500);
             } catch (InterruptedException e) {
             }
             backimg = "bg.png";
         }

     }

 }
  • 水果类
 package com.gxlee.lhj;

 public class Fruit {
     private int index = 0;
     private int nextIndex = 0;
     private int maxIndex = 5;
     private int width=94 ;//单个图片的宽度 并
     private int height = 102;//图片的高度  后面并没有用到 全部写死
     private int distance;
     private boolean alive = true;
     private boolean running ;
     private int speed;
     private int offset;
     public void setSpeed(int speed){
         if (speed<=0){
             speed = 0;
             alive = false;
         }
         this.speed = speed;
         setDisttance(distance+= speed);
     }

     public boolean isRunning() {
         return running;
     }

     public void setRunning(boolean running) {
         this.running = running;
     }

     public int getNextIndex() {
         return nextIndex;
     }
     public void setNextIndex(int nextIndex) {
         this.nextIndex = nextIndex;
     }
     public int getOffset() {
         return offset;
     }
     public void setOffset(int offset) {
         this.offset = offset;
     }

     public int getSpeed() {
         return speed;
     }
     public boolean isAlive() {
         return alive;
     }

     public void setAlive(boolean alive) {
         this.alive = alive;
     }

     public int getDistance() {
         return distance;
     }
     public void setDistance(int offset, boolean flag ) {
         int nextIndex = index==5?0:index+1;
         int dis = nextIndex*102+102-(offset);
         setDisttance(dis);
     }
     public void setDisttance(int distance){
         if(distance>=6*102){distance = distance % 102;}
         this.distance = distance;
         index = distance / 102;
         offset = distance % 102;
         nextIndex = (index == 5) ? 0 : index + 1;
     }

     public void setIndex(int index){
         this.index = index;
         distance = index*height;
     }

     public int getHeight(){
         return height;
     }
     public int getIndex() {
         return index;
     }

     public int getMaxIndex() {
         return maxIndex;
     }
     public void setMaxIndex(int maxIndex) {
         this.maxIndex = maxIndex;
     }
     public int getWidth() {
         return width;
     }

 }
  • 工具类
 package com.gxlee.lhj;

 import java.awt.image.BufferedImage;
 import java.io.File;
 import java.io.IOException;
 import java.util.HashMap;
 import java.util.Map;

 import javax.imageio.ImageIO;

 public class Utils {
     public static Map<String, BufferedImage> images = new HashMap<String,BufferedImage>();
     public static final int WIDTH = 440;
     public static final int HEIGHT =600;

     public static final int FRUIT_WIDTH = 94;
     public static final int FRUIT_HEIGHT = 102;

     static{
       File dir = new File("img");
       File[] files = dir.listFiles();
       for (File file:files) {
         try {
             BufferedImage image = ImageIO.read(file);
             images.put(file.getName(), image);
         } catch (IOException e) {
             //e.printStackTrace();
         }
     }
     }
 }

素材:

  • 主界面:

  • 水果:

JAVA小项目之摇奖机的更多相关文章

  1. Java小项目--坦克大战(version1.0)

    Java小项目--坦克大战<TankWar1.0> 这个小项目主要是练习j2se的基础内容和面向对象的思想.项目实现了基本的简单功能,我方一辆坦克,用上下左右键控制移动方向,按F键为发射炮 ...

  2. Java学习笔记三十:Java小项目之租车系统

    Java小项目之租车系统 一:项目背景介绍: 根据所学知识,编写一个控制台版的“呱呱租车系统” 功能: 1.展示所有可租车辆: 2.选择车型.租车量: 3.展示租车清单,包含:总金额.总载货量以及其车 ...

  3. Java小项目之:五子棋,你下棋下得过电脑吗?

    Java小项目之:五子棋,你下棋下得过电脑吗? Java五子棋功能要求: 1.创建窗口和设计一个棋盘界面 2.实现鼠标点击,棋子出现,黑白棋轮流下 3.能够判断五子相连输赢 4.添加重新开始,悔棋,退 ...

  4. java小项目之:植物大战僵尸,这个僵尸有点冷!内附素材源码

    Java小项目之:植物大战僵尸! <植物大战僵尸>是由PopCap Games开发的一款益智策略类单机游戏,于2009年5月5日发售,这款游戏可谓是无人不知无人不晓. 在我身边,上到40岁 ...

  5. Java小项目之:教你做个聊天系统!

    Java小项目之:聊天系统 今天给大家带来的java练手小项目是一个简单的聊天室,界面简单,操作不难. 分为注册系统,登录系统和聊天系统三部分,很适合java小白练手. 完整的源码和素材请关注并私信我 ...

  6. java小项目之:扫雷,这游戏没有你想的那么简单!

    扫雷 我之前分享的小项目和小游戏,电影购票.坦克大战.捕鱼达人.贪吃蛇等,虽然已经是耳熟能详人尽皆知的项目和游戏,但是保不齐真的有人没接触过. 今天分享的这个项目,我不相信没人接触过(仅限80后-00 ...

  7. java小项目之:抽奖系统!java初学者必备(内附源码)

    [Java]Java摇奖源码,Java抽奖源码,Java随机抽奖源码 任务描述 本次任务要求为某商场开发一套幸运抽奖系统,客户必须首先注册成为该商场会员,会员登录成功后,就可以参加抽奖活动了.注册 用 ...

  8. java小项目——抽奖系统

    来了来了!这不又到考试周了吗!愁人,又得复习,复习,复习!这段时间每天都在复习线代和高数!(说是复习,说实话其实是在预习,啊哈哈哈哈哈),得有一段时间都没有学到新的知识了,代码感觉都生疏了,惆怅.博客 ...

  9. java小项目之:象棋,羡慕你们有对象的!

    象棋,是我国传统棋类益智游戏,在中国有着悠久的历史,属于二人对抗性游戏的一种,由于用具简单,趣味性强,成为流行极为广泛的棋艺活动.中国象棋是中国棋文化也是中华民族的文化瑰宝. 象棋还有很多口诀,这是最 ...

随机推荐

  1. Spring3.0提供的表达式语言spel

    package com.zf.spel; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.D ...

  2. jQuery获取select、checkbox、radio的方法总结

    在进行网页的前后台交互的时候,经常需要获取单选框(radio).复选框(checkbox)以及下拉列表(select/dropdownlist)选中的值. 总结了一下,方便以后复习查看: 1.获取选中 ...

  3. Hibernate4 clob字段存取

    domain的字段: private Clob content; hibernate的xml映射 <property name="content" type="cl ...

  4. 手把手教你使用python复杂一点点的装饰器

    #只要@deco后面跟括号,都要 先传装饰器参数,返回 再传目标待装饰函数,返回 传目标函数的参数 #这个参数可以是类 def deco(arg):#装饰器的函数在这里传 print('0',arg) ...

  5. python3可变与不可变数据类型

    Python3中有六个标准的数据类型: Number(数字) String(字符串) List(列表) Dictionary(字典) Tuple(元组) Set(集合) 我理解的可变就是当一个变量创建 ...

  6. Vim记录

    Command Mode下: . 代表当前行 % 代表所有行 $ 代表结束行 :1,$normal i#     全部行前加#,同下 :%normal i# :read ! cd /usr/bin/; ...

  7. 转: 如何用linux命令修改linux主机ip网关子网掩码

    linux一般使用ifconfig命令修改linux主机的ip.网关或子网掩码. 1.命令格式: ifconfig [网络设备] [参数] 2.命令功能: ifconfig 命令用来查看和配置网络设备 ...

  8. Linux前传——今天的学习

    感觉每天早上搞一个C语言的趣味题,很不错,算是比较实际的事情了.而且,好多都不会,主要是算法,也有很多语法不知道,这样补强很有用.嵌入式方面的课题进展有条不紊,感觉相关寄存器和I/O的使用必须通过大量 ...

  9. ATR的基本结构与意义(无历史字符部分)

    Reset 3B FA 13 00 00 81 31 FE 45 4A 43 4F 50 34 31 56 32 32 31 96 复位应答 ATR TS( The Initial character ...

  10. 官网的许多Mobile开发教程,Blog和示例代码

    http://docwiki.embarcadero.com/RADStudio/Seattle/en/Mobile_Tutorials:_Mobile_Application_Development ...