• Java 动态写轮眼 SharinganJPanel (整理)


     
      1 /**
      2  *                    Java 动态写轮眼 SharingganJPanel (整理)     
      3  *                                 
      4  *                                          2016-1-2 深圳 南山平山村 曾剑锋
      5  * 设计声明:
      6  *         1、虽然岸本是日本人,而我个人作为其模仿者,依然想表示个人对其的敬意,希望作品
      7  *              不会玷污写轮眼的名声。
      8  *         2、由于本次设计包含过多数学计算,所以强烈建议您通过《注意事项》中的5查看图是
      9  *              如何设计的,先不要看源码,然后自己试图去设计,而您仅需要知道:计算机计算
     10  *              开方、三角函数、反三角等会造成误差,仅此而已。
     11  *         3、由于我本人在《动态中国太极图——Java原创》中改了一个注释错误,导致《动态中国
     12  *              太极图——Java原创》不能再次通过系统的审批,不知何故,所以导致大家可能看不
     13  *              到《动态中国太极图——Java原创》里面详细的注释,深表遗憾。同时也对我自己没
     14  *              能认真做好本质工作表示深深的反思。
     15  *         4、如果您对这个很好奇,那么请现查阅本人发表的《动态中国太极图——Java原创》(不
     16  *              知道还能不能通过审批)、《动态眨眼效果——Java原创》,因为那两个是这个设计
     17  *              的引导+铺垫。
     18  *         
     19  *         
     20  * 注意事项:
     21  *         1、本程序为java程序,同时感谢您花费宝贵的时间来阅读本文档;
     22  *         2、请注意包名为:practice,文件名为:SharinganJFrame(Sharingan是写轮眼的英文),
     23  *              注意检查,以防一些不必要的麻烦;
     24  *         3、在完成确认2中的内容后,本程序可以直接运行,因为本软件说明都在注释中;
     25  *         4、由于本设计是继《动态中国太极图——Java原创》、《动态眨眼效果——Java原创》后编
     26  *              写,所以在那里面已说明的东西,不再详述,同时由于个人能力、阅历等原因,有
     27  *              些细节可能并没有详细阐述,或者有疏漏,请谅解。                        
     28  *         5、您可以注释paint()方法中的一些代码,因为效果很直观,也许这样您理解得更快,
     29              建议如下:
     30  *             5.1 先看paint()方法第1条语句效果,把paint()方法中的其它语句注释掉;
     31  *             5.2 再看paint()方法第1、2条语句效果,把paint()方法中的其它语句注释掉;
     32  *             5.3 再看paint()方法第1、2、3条语句效果,把paint()方法中的其它语句注释掉;
     33  *             5.4 以上面的方法类推,直到paint()方法中没有语句被注释,相信等您看完,您就
     34  *                理解了。
     35  *
     36  * 设计目标:在一个JFrame中绘制一个动态的写轮眼(动漫《火影》中的特殊眼睛)。
     37  *
     38  * 设计说明:   
     39  *      相信很多人不喜欢看那些很长文字的说明,所以本人只简单介绍一下个人想法及遇到的一
     40  *        些问题:
     41  *          1、设计的源头来自我和同桌(程梦真)无意中提到写轮眼,所以打算把它用Java绘出来,
     42  *              而且要是动态的;
     43  *          2、目前的版本的写轮眼和最初设计的写轮眼有很大差别,很多单词的定义已经没有了
     44  *              当初的味道。
     45  *          3、绘制这个动态的写轮眼的时候遇到最严重的的问题是计算误差,就是苍老师说的
     46  *              精确但不准确,所以angleErr是用来做误差补偿的,当然这个还是不是很准确,没
     47  *              有更深入的去探究,由于本来就是娱乐,所以没打算去深究,如果你感兴趣,想去
     48  *              琢磨,请注意一下angleErr所出现的地方,本人因为这个误差,重画了进3遍才找
     49  *              出根本原因。
     50  *             
     51  *    2014-1-13 星期一 晴 8度 微风 南昌
     52  *
     53  */
     54 package demo;
     55 
     56 import java.awt.Color;
     57 import java.awt.Graphics;
     58 
     59 import javax.swing.JFrame;
     60 import javax.swing.JPanel;
     61 
     62 public class SharinganJPanel extends JPanel {
     63     //设置中心坐标,个人喜欢一种心点作为物体的坐标,物理里面成为质点
     64     static int centerX = 600/2;
     65     static int centerY = 600/2;
     66     //外圆半径,写轮眼转动所依赖的红线
     67     double extendCircleSemi = 25;                  // double extendCircleSemi = 200;
     68     //写轮眼的旋转部分有一个固定的大小的圆,刚开始设计的时候是定义为白色的,后来改为了红色,好看 ^_^
     69     double whiteOfSharingan = extendCircleSemi/3;  // double whiteOfSharingan = extendCircleSemi/6;
     70     //在上面的红色的圆旁边有一个随着旋转角度变大而变大的圆,其半径为miniCircleSemi
     71     double miniCircleSemi = 0;
     72     //这里用到了绘制太极时的思路,这个圆和上面的两个圆(whiteOfSharingan和miniCircleSemi)外切
     73     double sharinganSemi = 0;
     74     //旋转度角范围的变量,您可以通过观察旋转的循环角度是120*2
     75     int angleCircle = 0;
     76     //小圆(miniCircleSemi)和白圆(whiteOfSharingan)在外圆(extendCircleSemi)上的角度
     77     double angleOfWhiteMini = 0;
     78     //写轮眼沟玉圆(sharinganSemi)和白圆(whiteOfSharingan)在外圆(extendCircleSemi)的角度
     79     double angleOfwhiteShar = 0;
     80     //用于判断圆是否到达极限位置,还句话说就是是否到达了正确的角度,进行下一次循环
     81     boolean flag = true;
     82     //沟玉球心到弦(whiteOfSharingan圆中心和miniCircleSemi圆中心所连成的线)中心距离;
     83     double distansOfWhiteShar =0;
     84     //沟玉球心到中心点的距离,这一步主要是为了计算坐标
     85     double distansOfSharSemi = 0;
     86     //在绘图过程中,由于计算机计算开方、三角函数、反三角等造成了误差,这是一个补偿值,但要注意真正补偿的
     87     //误差为这个误差的angleErr*2/3,因为这个值是本人通过理想设置临界状态得到的值。
     88     double angleErr = 0.02500260489936114;
     89     //沟玉球(whiteOfSharingan)中的黑球半径,这个值是动态的
     90     int blackOfWhiteSemi = 0;
     91     //中心眼睛所占的长度
     92     int eyeLength = 300;
     93     //眼睛幅值
     94     int amplitude = 50;
     95     
     96     public SharinganJPanel() {
     97         
     98         startRun();
     99     }
    100     
    101     @Override
    102     public void paint(Graphics graphics) {
    103         System.out.println();
    104         super.paint(graphics);
    105         this.setBackground(Color.black);
    106         //绘制一个眼睛作为背景
    107         graphics.setColor(Color.red);
    108         for (int i = 0; i < eyeLength; i++) {
    109             graphics.drawLine(    centerX-eyeLength/2+i,
    110                                 centerY-(int)(Math.sin(Math.PI*i/eyeLength)*amplitude),
    111                                 centerX-eyeLength/2+i,
    112                                 centerY+(int)(Math.sin(Math.PI*i/eyeLength)*amplitude));
    113         }
    114         //在眼睛的中心绘制一个黑色的圆
    115         graphics.setColor(Color.black);
    116         graphics.fillOval(    centerX-90/2,
    117                             centerY-90/2,
    118                             90,
    119                             90);
    120         //在眼睛的中心绘制一个白色的圆
    121         graphics.setColor(Color.white);
    122         graphics.fillOval(    centerX-60/2/2/2,
    123                             centerY-60/2/2/2,
    124                             60/2/2,
    125                             60/2/2);
    126         //用于绘制3个不同角度、在不断变化、不同位置的太极图,图是有顺序的
    127         for (int i = 0; i < 3; i++) {
    128             //绘制写轮眼球(sharinganSemi)
    129             graphics.setColor(Color.red);
    130             graphics.fillArc(   (int)(centerX-sharinganSemi+Math.cos(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini/2+angleOfwhiteShar+angleErr*2/3)*distansOfSharSemi),
    131                                 (int)(centerY-sharinganSemi-Math.sin(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini/2+angleOfwhiteShar+angleErr*2/3)*distansOfSharSemi),
    132                                 (int)(sharinganSemi*2),
    133                                 (int)(sharinganSemi*2),angleCircle+i*120,180);
    134             //绘制写轮眼固定圆(whiteOfSharingan)
    135             graphics.setColor(Color.red);
    136             graphics.fillOval(  (int)(centerX-whiteOfSharingan+Math.cos(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
    137                                 (int)(centerY-whiteOfSharingan-Math.sin(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
    138                                 (int)(whiteOfSharingan*2),
    139                                 (int)(whiteOfSharingan*2));
    140             //绘制写轮眼黑球(miniCircleSemi)
    141             graphics.setColor(Color.black);
    142             graphics.fillOval(  (int)(centerX-miniCircleSemi+Math.cos(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini)*extendCircleSemi),
    143                                 (int)(centerY-miniCircleSemi-Math.sin(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini)*extendCircleSemi),
    144                                 (int)(miniCircleSemi*2),
    145                                 (int)(miniCircleSemi*2));
    146             //绘制写轮眼固定球内黑球(blackOfWhiteSemi)
    147             graphics.setColor(Color.black);
    148             graphics.fillOval(  (int)(centerX-(blackOfWhiteSemi+0.0)/120*whiteOfSharingan/2+Math.cos(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
    149                                 (int)(centerY-(blackOfWhiteSemi+0.0)/120*whiteOfSharingan/2-Math.sin(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
    150                                 (int)((blackOfWhiteSemi+0.0)/120*whiteOfSharingan),
    151                                 (int)((blackOfWhiteSemi+0.0)/120*whiteOfSharingan));
    152         }
    153         //绘制外圆
    154             graphics.setColor(Color.red);
    155             graphics.drawOval(  (int)(centerX-extendCircleSemi),
    156                                 (int)(centerY-extendCircleSemi),
    157                                 (int)(extendCircleSemi)*2,
    158                                 (int)(extendCircleSemi)*2);
    159     }
    160     public void startRun() {
    161         new Thread(){
    162             public void run() {
    163                 while(true){
    164                     if (flag) {
    165                         angleCircle += 2 ;
    166                         //沟玉白球中的黑球半径
    167                         blackOfWhiteSemi = angleCircle;
    168                         //System.out.println(angleCircle);
    169                         //根据目前写轮眼沟玉球转过角度来确定mini小球目前的对应的半径
    170                         miniCircleSemi = (angleCircle+0.0)/120*whiteOfSharingan;
    171                         //System.out.println(miniCircleSemi);
    172                         //沟玉球半径
    173                         sharinganSemi = miniCircleSemi+whiteOfSharingan;
    174                         //System.out.println(sharinganSemi);
    175                         //由于白球和mini小球都是在外圆上,所以通过弦对应的角度来求的小圆落后于白球的角度
    176                         angleOfWhiteMini = Math.asin(sharinganSemi/2/extendCircleSemi)*2;
    177                         //System.out.println(angleOfWhiteMini);
    178                         //沟玉球心到白球中心距离
    179                         distansOfWhiteShar = (whiteOfSharingan-miniCircleSemi)/2;
    180                         //沟玉球心到中心点的距离
    181                         distansOfSharSemi = Math.sqrt(  extendCircleSemi*extendCircleSemi
    182                                                         -((whiteOfSharingan+miniCircleSemi)/2)*((whiteOfSharingan+miniCircleSemi)/2)
    183                                                         +((whiteOfSharingan-miniCircleSemi)/2)*((whiteOfSharingan-miniCircleSemi)/2));
    184                         //沟玉球心和白求在中心圆上所成的角度
    185                         //通过这里可以可以求出由于计算机计算产生的计算误差为(0.02500260489936114)
    186                     //System.out.println(distansOfSharSemi);
    187                         angleOfwhiteShar = Math.asin(distansOfWhiteShar/2/distansOfSharSemi);
    188                         //System.out.println(angleOfwhiteShar);
    189                         if (angleCircle == 120) {
    190                             flag = false;
    191                         }
    192                     }else {
    193                         angleCircle += 2;
    194                         //沟玉白球中的黑球半径
    195                         blackOfWhiteSemi = 240-angleCircle;
    196                         //根据目前写轮眼沟玉球转过角度来确定mini小球目前的对应的半径
    197                         miniCircleSemi = (240.0-angleCircle)/120*whiteOfSharingan;
    198                         //miniCircleSemi = (angleCircle+0.0)/120*whiteOfSharingan;
    199                         //沟玉球半径
    200                         sharinganSemi = miniCircleSemi+whiteOfSharingan;
    201                         //由于白球和mini小球都是在外圆上,所以通过弦对应的角度来求的小圆落后于白球的角度
    202                         angleOfWhiteMini = Math.asin(sharinganSemi/2/extendCircleSemi)*2;
    203                         //沟玉球心到白球中心距离
    204                         distansOfWhiteShar = (whiteOfSharingan-miniCircleSemi)/2;
    205                         //沟玉球心到中心点的距离
    206                         distansOfSharSemi = Math.sqrt(  extendCircleSemi*extendCircleSemi
    207                                                         -((whiteOfSharingan+miniCircleSemi)/2)*((whiteOfSharingan+miniCircleSemi)/2)
    208                                                         +((whiteOfSharingan-miniCircleSemi)/2)*((whiteOfSharingan-miniCircleSemi)/2));
    209                         //沟玉球心和白求在中心圆上所成的角度
    210                         angleOfwhiteShar = Math.asin(distansOfWhiteShar/2/distansOfSharSemi);
    211                         if (angleCircle == 240) {
    212                             angleCircle = 0;
    213                             flag = true;
    214                         }
    215                     }
    216                     try {
    217                         Thread.sleep(20);
    218                     } catch (InterruptedException e) {
    219                         e.printStackTrace();
    220                     }
    221                     repaint();                
    222                 }
    223             };
    224         }.start();
    225     }
    226     public static void main(String[] args) {
    227         JFrame jFrame = new JFrame();
    228         jFrame.setTitle("Sharingan");
    229         jFrame.setSize(centerX*2, centerY*2);
    230         jFrame.getContentPane().setBackground(Color.black);
    231         jFrame.setLocationRelativeTo(null);
    232         jFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    233         
    234         JPanel jPanel = new SharinganJPanel();
    235         jFrame.add(jPanel);
    236         jFrame.setVisible(true);
    237     }
    238 }

    效果如图:

      

      

      

      

  • 相关阅读:
    计算最大公因数
    最大子序列和问题
    C++三大函数:析构函数、复制构造函数和operator=
    C++函数返回值传递
    C++动态内存分配
    Halcon Assistants
    网格细分算法
    HDevelop Guide
    MeshLab
    point cloud registration
  • 原文地址:https://www.cnblogs.com/zengjfgit/p/5094878.html
Copyright © 2020-2023  润新知