javaFX 屏幕飞絮效果,透明底

 效果:

 已修改,使用timeline,不用线程。画雪花曲线。

package funny;
import com.sun.org.slf4j.internal.Logger;
import com.sun.org.slf4j.internal.LoggerFactory;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.Image;
import javafx.scene.layout.Background;
import javafx.scene.layout.Pane;
import javafx.scene.layout.StackPane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import javafx.scene.canvas.Canvas;
import javafx.util.Duration;
import lombok.Data;

import java.awt.*;
import java.util.*;
import java.util.List;

/**
 * @Author sangchen
 * @Date 2021/7/8 10:36
 **/

public class Spider extends Application {

    double sonW = 200d;
    int sonC = 4;
    /**
     * 屏幕尺寸
     */
    Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
    private double width = screenSize.getWidth();
    private double height = screenSize.getHeight();
    GraphicsContext gc;

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

    @Override
    public void start(Stage primaryStage) {
        Pane root = new StackPane();
        Canvas canvas = new Canvas(width, height);
        gc = canvas.getGraphicsContext2D();
        canvas.setOnMouseClicked(event -> {
            System.out.println("111");
        });
        root.getChildren().add(canvas);
        //透明底
        root.setBackground(Background.EMPTY);
        primaryStage.initStyle(StageStyle.TRANSPARENT);
        Scene scene = new Scene(root, width, height);
        scene.setFill(null);
        primaryStage.setScene(scene);
        //常驻顶层
        primaryStage.setAlwaysOnTop(true);
        primaryStage.show();
        funny();
    }

    private void funny() {
        Random random = new Random();
        gc.setLineWidth(1);
        gc.setStroke(Color.rgb(57, 125, 198));
        List<Sth> list = new ArrayList();
        Double randomFx[] = {0.1d, 0.15d, 0.2d, 0.25d};
        Double randomFy[] = {0.1d, 0.2d, 0.3d, 0.15d};
        for (int i = 0; i < sonC; i++) {
            //随机出生地
            double x = random.nextInt((int) width);
            double y = random.nextInt((int) height);
            int fx = random.nextInt(4) % 2 == 0 ? -1 : 1;
            int fy = random.nextInt(4) % 2 == 0 ? -1 : 1;
            Sth sth = new Sth(x, y, fx, fy, (random.nextInt(4) % 2 == 0 ? -1 : 1) * (0.001 * random.nextInt(1000)));
            list.add(sth);
        }
        Timeline timeline = new Timeline();
        // 动画执行的次数(Timeline.INDEFINITE表示随机,就是鬼才知道什么结束的那种)
        timeline.setCycleCount(Timeline.INDEFINITE);
        // 是否还原为初始状态(如果设置为true,会在执行次数内还会切换,至于这个初始状态什么意思自己体会吧)
        timeline.setAutoReverse(true);
        KeyFrame keyFrame = new KeyFrame(Duration.millis(1), new EventHandler<ActionEvent>() {
            public void handle(ActionEvent t) {
                gc.clearRect(0, 0, width, height);
                int k = 0;
                for (Sth sth : list) {
                    drawSth(sth);
                    k++;
                    double x = sth.getX();
                    double y = sth.getY();
                    x += randomFx[k % randomFx.length] * sth.fx;
                    y += randomFy[k % randomFy.length] * sth.fy;
                    //撞墙折返x
                    if (x > width - sonW/10) {
                        System.out.println("x 大了");
                        sth.setFx(-1);
                        sth.setOffset((random.nextInt(4) % 2 == 0 ? -1 : 1) * (0.001 * random.nextInt(1000)));
                    }
                    if (x < sonW/10) {
                        System.out.println("x 小了");
                        sth.setFx(1);
                    }
                    //撞墙折返y
                    if (y > height - sonW/10) {
                        sth.setFy(-1);
                        sth.setOffset((random.nextInt(4) % 2 == 0 ? -1 : 1) * (0.001 * random.nextInt(1000)));
                    }
                    if (y < sonW/10) {
                        System.out.println("y 小了");
                        sth.setFy(1);
                    }
                    //碰撞折返
                    for (Sth s : list) {
                        if (s != sth) {
                            if (Math.abs(s.getX() - sth.getX()) < sonW * 2
                                    && Math.abs(s.getY() - sth.getY()) < sonW * 2) {
                                int fyt = s.getFy();
                                int fxt = s.getFx();
                                sth.setFy(s.getFy());
                                sth.setFx(s.getFx());
                                s.setFx(fxt);
                                s.setFy(fyt);
                            }
                        }

                    }
                    sth.setX(x);
                    sth.setY(y);
                    sth.setAngle(sth.angle + 0.01d * sth.offset);
                }
            }
        });
        timeline.getKeyFrames().add(keyFrame);
        timeline.play();
    }

    private void drawSth(Sth sth) {

        int n = 4;
        double x = sth.getX();
        double y = sth.getY();
        double len = sonW / 3;
        double angle = sth.getAngle();
        kochCurve(x, y, angle, len, n);

        x = x + len * Math.cos(angle);
        y = y - len * Math.sin(angle);
        angle -= Math.PI * 2 / 3;
        kochCurve(x, y, angle, len, n);

        x = x + len * Math.cos(angle);
        y = y - len * Math.sin(angle);
        angle -= Math.PI * 2 / 3;
        kochCurve(x, y, angle, len, n);

    }

    private void kochCurve(double x, double y, double angle, double len, int n) {
        if (n == 0) {
            double x1 = x + len * Math.cos(angle);
            double y1 = y - len * Math.sin(angle);
            gc.strokeLine(x, y, x1, y1);
        } else {
            n = n - 1;
            len /= 3;
            kochCurve(x, y, angle, len, n);
            x = x + len * Math.cos(angle);
            y = y - len * Math.sin(angle);
            angle += Math.PI * 1 / 3;
            kochCurve(x, y, angle, len, n);

            x = x + len * Math.cos(angle);
            y = y - len * Math.sin(angle);
            angle -= Math.PI * 2 / 3;
            kochCurve(x, y, angle, len, n);

            x = x + len * Math.cos(angle);
            y = y - len * Math.sin(angle);
            angle += Math.PI * 1 / 3;
            kochCurve(x, y, angle, len, n);
        }
    }

    @Data
    class Sth {
        double offset;  //随便给个偏移量
        double x, y; //坐标
        int fx, fy; //飞行方向
        double angle = 0d;

        Sth(double x, double y, int fx, int fy, double offset) {
            this.x = x;
            this.y = y;
            this.fx = fx;
            this.fy = fy;
            this.offset = offset;
        }
    }
}

撸的我心态崩了,数学知识忘得差不多了,雪花画不出来

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值