Powered by PulpCore

Starfield.java  bg.jpg  star0.png  star1.png  star2.png 

// Starfield
// Scroll the mouse wheel or press the arrow keys to travel through the cosmos.
// Shows mouse wheel input, custom sprites, and motion blur.
import pulpcore.image.BlendMode;
import pulpcore.Input;
import pulpcore.math.CoreMath;
import pulpcore.scene.Scene2D;
import pulpcore.sprite.ImageSprite;
import pulpcore.Stage;
import pulpcore.image.filter.MotionBlur;

public class Starfield extends Scene2D {
    
    int numStarImages = 3;
    int numStars = 50;
    int zoomTimeRemaining;
    int zoomX;
    int zoomY;
    double zoomSpeed;

    @Override
    public void load() {
        add(new ImageSprite("bg.jpg", 0, 0));
        
        for (int i = 0; i < numStars; i++) {
            int r = CoreMath.rand(numStarImages - 1);
            add(new Star("star" + r + ".png"));
        }
    }
    
    @Override
    public void update(int elapsedTime) {
        if (Input.getMouseWheelRotation() > 0) {
            zoom(Input.getMouseWheelX(), Input.getMouseWheelY(), -.02);
        }
        else if (Input.getMouseWheelRotation() < 0) {
            zoom(Input.getMouseWheelX(), Input.getMouseWheelY(), 0.75);
        }
        
        if (Input.isDown(Input.KEY_DOWN)) {
            zoom(Stage.getWidth() / 2, Stage.getHeight() / 2, -.02);
        }

        if (Input.isDown(Input.KEY_UP)) {
            zoom(Stage.getWidth() / 2, Stage.getHeight() / 2, 0.75);
        }
        
        zoomTimeRemaining -= elapsedTime;
    }
    
    void zoom(int x, int y, double speed) {
        zoomX = x;
        zoomY = y;
        zoomSpeed = speed;
        zoomTimeRemaining = 300;
    }
    
    class Star extends ImageSprite {

        MotionBlur motionBlur = new MotionBlur();
        double z;
        
        public Star(String image) {
            super(image, CoreMath.rand(0, Stage.getWidth()), CoreMath.rand(0, Stage.getHeight()));
            setZ(CoreMath.rand(1.0, 4.0));
            setBlendMode(BlendMode.Add());
            setFilter(motionBlur);
            motionBlur.distance.set(0);
        }
        
        @Override
        public void update(int elapsedTime) {
            super.update(elapsedTime);
            
            if (zoomTimeRemaining > 0) {
                double motionBlurDistance = zoomSpeed * z * z * 1.5;
                double speed = zoomSpeed * z * z / 3000;
                double dx = (x.get() - zoomX) * elapsedTime * speed;
                double dy = (y.get() - zoomY) * elapsedTime * speed;
                setZ(z + elapsedTime * speed);
                setLocation(x.get() + dx, y.get() + dy);
                
                if (x.get() < 0 || x.get() >= Stage.getWidth() ||
                    y.get() < 0 || y.get() >= Stage.getHeight())
                {
                    setZ(CoreMath.rand(1.0, 3.0));
                    setLocation(
                        zoomX + CoreMath.rand(-Stage.getWidth() / 10, Stage.getWidth() / 10),
                        zoomY + CoreMath.rand(-Stage.getHeight() / 10, Stage.getHeight() / 10));
                    motionBlur.distance.set(0);
                }
                else {
                    motionBlur.angle.set(Math.atan2(dy, dx));
                    if (zoomTimeRemaining <= 100) {
                        // Wind down the motion blur
                        if (!motionBlur.distance.isAnimating()) {
                            motionBlur.distance.animateTo(0, zoomTimeRemaining);
                        }
                    }
                    else {
                        motionBlur.distance.set(motionBlurDistance);
                    }
                }
            }
            else {
                motionBlur.distance.set(0);
            }
        }
        
        void setZ(double z) {
            this.z = z;
            setSize(z * 5, z * 5);
            alpha.set(z >= 2 ? 255 : (int)(255 * (z-1)));
        }
    }    
}