歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

動態寫輪眼,絕對值得你擁有的Java原創作品

/**
 * 設計聲明:
 *        1、雖然岸本是日本人,而我個人作為其模仿者,依然想表示個人對其的敬意,希望作品不會玷污寫輪眼的名聲。
 *        2、由於本次設計包含過多數學計算,所以強烈建議您通過《注意事項》中的5查看圖是如何設計的,先不要看源碼,
 *            然後自己試圖去設計,而您僅需要知道:計算機計算開方、三角函數、反三角等會造成誤差,僅此而已。
 *        3、由於我本人在《動態中國太極圖——Java原創》中改了一個注釋錯誤,導致《動態中國太極圖——Java原創》
 *            不能再次通過系統的審批,不知何故,所以導致大家可能看不到《動態中國太極圖——Java原創》裡面詳細
 *            的注釋,深表遺憾。同時也對我自己沒能認真做好本質工作表示深深的反思。
 *        4、如果您對這個很好奇,那麼請現查閱本人發表的《動態中國太極圖——Java原創》(不知道還能不能通過審批)、
 *            《動態眨眼效果——Java原創》,因為那兩個是這個設計的引導+鋪墊。
 *       
 *       
 * 注意事項:
 *        1、本程序為java程序,同時感謝您花費寶貴的時間來閱讀本文檔;
 *        2、請注意包名為:practice,文件名為:SharinganJFrame(Sharingan是寫輪眼的英文),注意檢查,
 *                以防一些不必要的麻煩;
 *        3、在完成確認2中的內容後,本程序可以直接運行,因為本軟件說明都在注釋中;
 *        4、由於本設計是繼《動態中國太極圖——Java原創》、《動態眨眼效果——Java原創》後編寫,所以在那裡
 *                面已說明的東西,不再詳述,同時由於個人能力、閱歷等原因,有些細節可能並沒有詳細闡述,或者
 *                有疏漏,請諒解。                     
 *        5、您可以注釋paint()方法中的一些代碼,因為效果很直觀,也許這樣您理解得更快,建議如下:
 *            5.1 先看paint()方法第1條語句效果,把paint()方法中的其它語句注釋掉;
 *            5.2 再看paint()方法第1、2條語句效果,把paint()方法中的其它語句注釋掉;
 *            5.3 再看paint()方法第1、2、3條語句效果,把paint()方法中的其它語句注釋掉;
 *            5.4 以上面的方法類推,直到paint()方法中沒有語句被注釋,相信等您看完,您就理解了。
 *
 * 設計目標:在一個JFrame中繪制一個動態的寫輪眼(動漫《火影》中的特殊眼睛)。
 *
 * 設計說明: 
 *      相信很多人不喜歡看那些很長文字的說明,所以本人只簡單介紹一下個人想法及遇到的一些問題:
 *          1、設計的源頭來自我和同桌(程夢真)無意中提到寫輪眼,所以打算把它用Java繪出來,而且要是動態的;
 *          2、目前的版本的寫輪眼和最初設計的寫輪眼有很大差別,很多單詞的定義已經沒有了當初的味道。
 *            3、繪制這個動態的寫輪眼的時候遇到最嚴重的的問題是計算誤差,就是蒼老師說的精確但不准確,所以
 *                angleErr是用來做誤差補償的,當然這個還是不是很准確,沒有更深入的去探究,由於本來就是娛
 *                樂,所以沒打算去深究,如果你感興趣,想去琢磨,請注意一下angleErr所出現的地方,本人因為
 *                這個誤差,重畫了進3遍才找出根本原因。
 *           
 *    2014-1-14 星期二
 *
 */
package practice;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JFrame;
public class SharinganJFrame extends JFrame {
    //設置中心坐標,個人喜歡一種心點作為物體的坐標,物理裡面成為質點
    int centerX = 1024/2;
    int centerY = 768/2;
    //外圓半徑,寫輪眼轉動所依賴的紅線
    double extendCircleSemi = 25;
    //寫輪眼的旋轉部分有一個固定的大小的圓,剛開始設計的時候是定義為白色的,後來改為了紅色,好看 ^_^
    double whiteOfSharingan = extendCircleSemi/3;
    //在上面的紅色的圓旁邊有一個隨著旋轉角度變大而變大的圓,其半徑為miniCircleSemi
    double miniCircleSemi = 0;
    //這裡用到了繪制太極時的思路,這個圓和上面的兩個圓(whiteOfSharingan和miniCircleSemi)外切
    double sharinganSemi = 0;
    //旋轉度角范圍的變量,您可以通過觀察旋轉的循環角度是120*2
    int angleCircle = 0;
    //小圓(miniCircleSemi)和白圓(whiteOfSharingan)在外圓(extendCircleSemi)上的角度
    double angleOfWhiteMini = 0;
    //寫輪眼溝玉圓(sharinganSemi)和白圓(whiteOfSharingan)在外圓(extendCircleSemi)的角度
    double angleOfwhiteShar = 0;
    //用於判斷圓是否到達極限位置,還句話說就是是否到達了正確的角度,進行下一次循環
    boolean flag = true;
    //溝玉球心到弦(whiteOfSharingan圓中心和miniCircleSemi圓中心所連成的線)中心距離;
    double distansOfWhiteShar =0;
    //溝玉球心到中心點的距離,這一步主要是為了計算坐標
    double distansOfSharSemi = 0;
    //在繪圖過程中,由於計算機計算開方、三角函數、反三角等造成了誤差,這是一個補償值,但要注意真正補償的
    //誤差為這個誤差的angleErr*2/3,因為這個值是本人通過理想設置臨界狀態得到的值。
    double angleErr = 0.02500260489936114;
    //溝玉球(whiteOfSharingan)中的黑球半徑,這個值是動態的
    int blackOfWhiteSemi = 0;
    //中心眼睛所占的長度
    int eyeLength = 300;
    //眼睛幅值
    int amplitude = 50;
             
    public SharinganJFrame() {
        this.setTitle("Sharingan");
        this.setSize(centerX*2, centerY*2);
        this.getContentPane().setBackground=\'#\'"        startRun();
        this.setVisible(true);
    }
             
    @Override
    public void paint(Graphics graphics) {
        super.paint(graphics);
        //繪制一個眼睛作為背景
        graphics.setColor(Color.red);
        for (int i = 0; i < eyeLength; i++) {
            graphics.drawLine(    centerX-eyeLength/2+i,
                                centerY-(int)(Math.sin(Math.PI*i/eyeLength)*amplitude),
                                centerX-eyeLength/2+i,
                                centerY+(int)(Math.sin(Math.PI*i/eyeLength)*amplitude));
        }
        //在眼睛的中心繪制一個黑色的圓
        graphics.setColor(Color.black);
        graphics.fillOval(    centerX-90/2,
                            centerY-90/2,
                            90,
                            90);
        //在眼睛的中心繪制一個白色的圓
        graphics.setColor(Color.white);
        graphics.fillOval(    centerX-60/2/2/2,
                            centerY-60/2/2/2,
                            60/2/2,
                            60/2/2);
        //用於繪制3個不同角度、在不斷變化、不同位置的太極圖,圖是有順序的
        for (int i = 0; i < 3; i++) {
            //繪制寫輪眼球(sharinganSemi)
            graphics.setColor(Color.red);
            graphics.fillArc(    (int)(centerX-sharinganSemi+Math.cos(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini/2+angleOfwhiteShar+angleErr*2/3)*distansOfSharSemi),
                                (int)(centerY-sharinganSemi-Math.sin(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini/2+angleOfwhiteShar+angleErr*2/3)*distansOfSharSemi),
                                (int)(sharinganSemi*2),
                                (int)(sharinganSemi*2),angleCircle+i*120,180);
            //繪制寫輪眼固定圓(whiteOfSharingan)
            graphics.setColor(Color.red);
            graphics.fillOval(    (int)(centerX-whiteOfSharingan+Math.cos(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
                                (int)(centerY-whiteOfSharingan-Math.sin(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
                                (int)(whiteOfSharingan*2),
                                (int)(whiteOfSharingan*2));
            //繪制寫輪眼黑球(miniCircleSemi)
            graphics.setColor(Color.black);
            graphics.fillOval(    (int)(centerX-miniCircleSemi+Math.cos(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini)*extendCircleSemi),
                                (int)(centerY-miniCircleSemi-Math.sin(Math.PI*(angleCircle+90+(i*120))/180-angleOfWhiteMini)*extendCircleSemi),
                                (int)(miniCircleSemi*2),
                                (int)(miniCircleSemi*2));
            //繪制寫輪眼固定球內黑球(blackOfWhiteSemi)
            graphics.setColor(Color.black);
            graphics.fillOval(    (int)(centerX-(blackOfWhiteSemi+0.0)/120*whiteOfSharingan/2+Math.cos(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
                                (int)(centerY-(blackOfWhiteSemi+0.0)/120*whiteOfSharingan/2-Math.sin(Math.PI*(angleCircle+90+(i*120))/180)*extendCircleSemi),
                                (int)((blackOfWhiteSemi+0.0)/120*whiteOfSharingan),
                                (int)((blackOfWhiteSemi+0.0)/120*whiteOfSharingan));
        }
        //繪制外圓
            graphics.setColor(Color.red);
            graphics.drawOval(    (int)(centerX-extendCircleSemi),
                                (int)(centerY-extendCircleSemi),
                                (int)(extendCircleSemi)*2,
                                (int)(extendCircleSemi)*2);
    }
    public void startRun() {
        new Thread(){
            public void run() {
                while(true){
                    if (flag) {
                        angleCircle += 2 ;
                        //溝玉白球中的黑球半徑
                        blackOfWhiteSemi = angleCircle;
                        //System.out.println(angleCircle);
                        //根據目前寫輪眼溝玉球轉過角度來確定mini小球目前的對應的半徑
                        miniCircleSemi = (angleCircle+0.0)/120*whiteOfSharingan;
                        //System.out.println(miniCircleSemi);
                        //溝玉球半徑
                        sharinganSemi = miniCircleSemi+whiteOfSharingan;
                    //System.out.println(sharinganSemi);
                        //由於白球和mini小球都是在外圓上,所以通過弦對應的角度來求的小圓落後於白球的角度
                        angleOfWhiteMini = Math.asin(sharinganSemi/2/extendCircleSemi)*2;
                        //System.out.println(angleOfWhiteMini);
                        //溝玉球心到白球中心距離
                        distansOfWhiteShar = (whiteOfSharingan-miniCircleSemi)/2;
                        //溝玉球心到中心點的距離
                        distansOfSharSemi = Math.sqrt(    extendCircleSemi*extendCircleSemi
                                                        -((whiteOfSharingan+miniCircleSemi)/2)*((whiteOfSharingan+miniCircleSemi)/2)
                                                        +((whiteOfSharingan-miniCircleSemi)/2)*((whiteOfSharingan-miniCircleSemi)/2));
                        //溝玉球心和白求在中心圓上所成的角度
                        //通過這裡可以可以求出由於計算機計算產生的計算誤差為(0.02500260489936114)
                    //System.out.println(distansOfSharSemi);
                        angleOfwhiteShar = Math.asin(distansOfWhiteShar/2/distansOfSharSemi);
                        //System.out.println(angleOfwhiteShar);
                        if (angleCircle == 120) {
                            flag = false;
                        }
                    }else {
                        angleCircle += 2;
                        //溝玉白球中的黑球半徑
                        blackOfWhiteSemi = 240-angleCircle;
                        //根據目前寫輪眼溝玉球轉過角度來確定mini小球目前的對應的半徑
                        miniCircleSemi = (240.0-angleCircle)/120*whiteOfSharingan;
                        //miniCircleSemi = (angleCircle+0.0)/120*whiteOfSharingan;
                        //溝玉球半徑
                        sharinganSemi = miniCircleSemi+whiteOfSharingan;
                        //由於白球和mini小球都是在外圓上,所以通過弦對應的角度來求的小圓落後於白球的角度
                        angleOfWhiteMini = Math.asin(sharinganSemi/2/extendCircleSemi)*2;
                        //溝玉球心到白球中心距離
                        distansOfWhiteShar = (whiteOfSharingan-miniCircleSemi)/2;
                        //溝玉球心到中心點的距離
                        distansOfSharSemi = Math.sqrt(    extendCircleSemi*extendCircleSemi
                                                        -((whiteOfSharingan+miniCircleSemi)/2)*((whiteOfSharingan+miniCircleSemi)/2)
                                                        +((whiteOfSharingan-miniCircleSemi)/2)*((whiteOfSharingan-miniCircleSemi)/2));
                        //溝玉球心和白求在中心圓上所成的角度
                        angleOfwhiteShar = Math.asin(distansOfWhiteShar/2/distansOfSharSemi);
                        if (angleCircle == 240) {
                            angleCircle = 0;
                            flag = true;
                        }
                    }
                    try {
                        Thread.sleep(20);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    repaint();             
                }
            };
        }.start();
    }
    public static void main(String[] args) {
        new SharinganJFrame();
    }
}

動態眨眼效果---Java實現強大的作品  http://www.linuxidc.com/Linux/2014-01/95249.htm

Copyright © Linux教程網 All Rights Reserved