javaFX2 漂亮的礼花弹动画

javaFX2 漂亮的礼花弹动画

博文日期:  2013-4-4 14:06:33   分类:   JAVAFX  |  
 
这是一个有javaFX2.2 写的一个礼花弹动画希望能给javaFX爱好者一下灵感!
源代码下载地址:梦续残源  http://mxcyk.com/?post=494
/**@author mxcyk.com
 *一个示例,演示如何画画形状,适用于视觉  
 * 的影响,混合颜色重叠的对象和动画对象。
 * @see javafx.scene.canvas.Canvas
 * @see javafx.scene.canvas.GraphicsContext
 * @see javafx.scene.effect.BlendMode
 * @see javafx.scene.effect.BoxBlur
 * @see javafx.scene.shape.Circle
 * @see javafx.scene.Group
 * @see javafx.scene.paint.LinearGradient
 * @see javafx.animation.Timeline
 */
public class Fireworks extends Application {
    private final SanFranciscoFireworks sanFranciscoFireworks = new SanFranciscoFireworks();
    
    private void init(Stage primaryStage) {
        
        Group root = new Group();
        primaryStage.setScene(new Scene(root));
        root.getChildren().add(sanFranciscoFireworks);
    }

    @Override public void stop() {
        sanFranciscoFireworks.stop();
    }

    public void play() {
        sanFranciscoFireworks.start();
    }
    
    public static class SanFranciscoFireworks extends Pane {
        private final AnimationTimer timer;
        private final Canvas canvas;
        private final ImageView background;
        private final List particles = new ArrayList();
        private final Paint[] colors;
        private int countDownTillNextFirework = 40;
        
        public SanFranciscoFireworks() {
            // create a color palette of 180 colors
            colors = new Paint[181];
            colors[0] = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, 
                        new Stop(0, Color.WHITE),
                        new Stop(0.2, Color.hsb(59, 0.38, 1)),
                        new Stop(0.6, Color.hsb(59, 0.38, 1,0.1)),
                        new Stop(1, Color.hsb(59, 0.38, 1,0))
                        );
            for (int h=0;h<360;h+=2) {
                colors[1+(h/2)] = new RadialGradient(0, 0, 0.5, 0.5, 0.5, true, CycleMethod.NO_CYCLE, 
                        new Stop(0, Color.WHITE),
                        new Stop(0.2, Color.hsb(h, 1, 1)),
                        new Stop(0.6, Color.hsb(h, 1, 1,0.1)),
                        new Stop(1, Color.hsb(h, 1, 1,0))
                        );
            }
            // create canvas
            canvas = new Canvas(1024, 500);

            canvas.setBlendMode(BlendMode.ADD);
            canvas.setEffect(new Reflection(0,0.4,0.15,0));
            background = new ImageView(getClass().getResource("sf.jpg").toExternalForm());
            getChildren().addAll(background,canvas);
            // create animation timer that will be called every frame
            // final AnimationTimer timer = new AnimationTimer() {
            timer = new AnimationTimer() {

                @Override public void handle(long now) {
                    GraphicsContext gc = canvas.getGraphicsContext2D();
                    // clear area with transparent black
                    gc.setFill(Color.rgb(0, 0, 0, 0.2));
                    gc.fillRect(0, 0, 1024, 708);
                    // draw fireworks
                    drawFireworks(gc);
                    // countdown to launching the next firework
                    if (countDownTillNextFirework == 0) {
                        countDownTillNextFirework = 10 + (int)(Math.random()*30);
                        fireParticle();
                    }
                    countDownTillNextFirework --;
                }
            };
        }
        
        public void start() { timer.start(); }
        public void stop() { timer.stop(); }

        /**
         * 调整大小,使背景图像比例和中心。
         */
        @Override protected void layoutChildren() {
            // final double w = 480.0;
            // final double h = 360.0;
            final double w = getWidth();
            final double h = getHeight();
            final double scale = Math.min(w/1024d, h/708d);
            final int width = (int)(1024*scale);
            final int height = (int)(708*scale);
            final int x = (int)((w-width)/2);
            final int y = (int)((h-height)/2);
            background.relocate(x, y);
            background.setFitWidth(width);
            background.setFitHeight(height);
            canvas.relocate(x, y);
            canvas.setWidth(width);
            canvas.setHeight(height * 0.706);
        }
    
        private void drawFireworks(GraphicsContext gc) {
            Iterator iter = particles.iterator();
            List newParticles = new ArrayList();
            while(iter.hasNext()) {
                Particle firework = iter.next();
                // 如果更新返回true,则粒子已过期
                if(firework.update()) {
                    // 从这些画中删除粒子
                    iter.remove();
                    // 检查它是否应该被爆炸
                    if(firework.shouldExplodeChildren) {
                        if(firework.size == 9) {
                            explodeCircle(firework, newParticles);
                        } else if(firework.size == 8) {
                            explodeSmallCircle(firework, newParticles);
                        }
                    }
                }
                firework.draw(gc);
            }
            particles.addAll(newParticles);
        }
        
        private void fireParticle() {
            particles.add(new Particle(
                canvas.getWidth()*0.5, canvas.getHeight()+10,
                Math.random() * 5 - 2.5, 0, 
                0, 150 + Math.random() * 100,
                colors[0], 9,
                false, true, true));
        }


        private void explodeCircle(Particle firework, List newParticles) {
            final int count = 20 + (int)(60*Math.random());
            final boolean shouldExplodeChildren = Math.random() > 0.5;
            final double angle = (Math.PI * 2) / count;
            final int color = (int)(Math.random()*colors.length);
            for(int i=count; i>0; i--) {
                double randomVelocity = 4 + Math.random() * 4;
                double particleAngle = i * angle;
                newParticles.add(
                    new Particle(
                        firework.posX, firework.posY, 
                        Math.cos(particleAngle) * randomVelocity, Math.sin(particleAngle) * randomVelocity,
                        0, 0, 
                        colors[color], 
                        8,
                        true, shouldExplodeChildren, true));
            }
        }

        private void explodeSmallCircle(Particle firework, List newParticles) {
            final double angle = (Math.PI * 2) / 12;
            for(int count=12; count>0; count--) {
                double randomVelocity = 2 + Math.random() * 2;
                double particleAngle = count * angle;
                newParticles.add(
                    new Particle(
                        firework.posX, firework.posY, 
                        Math.cos(particleAngle) * randomVelocity, Math.sin(particleAngle) * randomVelocity,
                        0, 0, 
                        firework.color, 
                        4,
                        true, false, false));
            }
        }
    }


    /**
     * 绘制一个圆,一个简单的粒子。
     */
    public static class Particle {
        private static final double GRAVITY = 0.06;
        // 动画属性和着色
        double alpha;
        final double easing;
        double fade;
        double posX;
        double posY;
        double velX;
        double velY;
        final double targetX;
        final double targetY;
        final Paint color;
        final int size;
        final boolean usePhysics;
        final boolean shouldExplodeChildren;
        final boolean hasTail;
        double lastPosX;
        double lastPosY;
        
        public Particle(double posX, double posY, double velX, double velY, double targetX, double targetY, 
                Paint color,int size, boolean usePhysics, boolean shouldExplodeChildren, boolean hasTail) {
            this.posX = posX;
            this.posY = posY;
            this.velX = velX;
            this.velY = velY;
            this.targetX = targetX;
            this.targetY = targetY;
            this.color = color;
            this.size = size;
            this.usePhysics = usePhysics;
            this.shouldExplodeChildren = shouldExplodeChildren;
            this.hasTail = hasTail;
            this.alpha    = 1;
            this.easing   = Math.random() * 0.02;
            this.fade     = Math.random() * 0.1;
        }

        public boolean update() {
            lastPosX = posX;
            lastPosY = posY;
            if(this.usePhysics) { //一路下跌
                velY += GRAVITY;
                posY += velY;
                this.alpha -= this.fade; // 淡出颗粒
            } else { // on way up
                double distance = (targetY - posY);
                // ease the position
                posY += distance * (0.03 + easing);
                // cap to 1
                alpha = Math.min(distance * distance * 0.00005, 1);
            }
            posX += velX;
            return alpha < 0.005;
        }

        public void draw(GraphicsContext context) {
            final double x = Math.round(posX);
            final double y = Math.round(posY);
            final double xVel = (x - lastPosX) * -5;
            final double yVel = (y - lastPosY) * -5;
            // 所有的绘图设置这种粒子的不透明度为
            context.setGlobalAlpha(Math.random() * this.alpha);
            // draw particle
            context.setFill(color);
            context.fillOval(x-size, y-size, size+size, size+size);
            // draw the arrow triangle from where we were to where we are now
            if (hasTail) {
                context.setFill(Color.rgb(255,255,255,0.3));
                context.fillPolygon(new double[]{posX + 1.5,posX + xVel,posX - 1.5}, 
                        new double[]{posY,posY + yVel,posY}, 3);
            }
        }
    }

    @Override public void start(Stage primaryStage) throws Exception {
        init(primaryStage);
        primaryStage.show();
        primaryStage.setTitle("mxcyk.com 一个漂亮的礼花弹动画");
        play();
    }

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

你可能感兴趣的:(javafx)