Resource Image to Particles

Discussion in 'Spigot Plugin Development' started by Backstabber1, Aug 2, 2020.

  1. So i was reading a thread over here about making particle wings & i got the idea of somehow converting an image created in photoshop or any other pixel art software into particles which can be displayed in game.
    Usage:
    Copy this class into your project:
    Code (Java):
    package me.backstabber.tests;

    import java.awt.image.BufferedImage;
    import java.util.HashMap;
    import java.util.Map;

    import org.bukkit.Color;
    import org.bukkit.Location;
    import org.bukkit.util.Vector;

    /**
    * Simple Utility to have images as particles
    * @author Backstabber
    *
    */

    public class ImageParticles {
       
        private Map<Vector,Color> particles=new HashMap<Vector, Color>();
        private Vector anchor=new Vector(0,0,0);
        private double ratio=0.2;
        private BufferedImage image;
        private int clearence=300;
        /**
         * Create a new object
         * @param image of the particles structure you want
         * @param scanQuality is the quality of the scanned image in particles (1 for default 2 for half etc)
         */

        public ImageParticles(BufferedImage image,int scanQuality) {
            this.image=image;
            renderParticles(Math.abs(scanQuality));
        }
        /**
         * Set the anchor point for the particles structure
         * by default the anchor will be the bottom right
         * @param x (the x axis of the image or width)
         * @param y (the y axis of the image or height
         */

        public void setAnchor(int x,int y) {
            anchor=new Vector(x, y, 0);
        }
        /**
         * Sets the ratio between blocks & pixels i.e block/pixel (0.1 means 10 pixels in 1 block space)
         * @param ratio
         */

        public void setDisplayRatio(double ratio) {
            this.ratio=ratio;
        }
        /**
         * Get a map of locations & colors on which particles are to be displayed
         * @param location of the anchor point
         * @param pitch (if you want picture to be rotated)
         * @param yaw  (if you want picture to be rotated)
         * @return map of the locations & color
         */

        public Map<Location, Color> getParticles(Location location,double pitch,double yaw) {
            Map<Location, Color> map=new HashMap<Location, Color>();
            for(Vector vector:particles.keySet()) {
                Vector difference=vector.clone().subtract(anchor).multiply(ratio);
                Vector v=rotateAroundAxisX(difference,pitch);
                v=rotateAroundAxisY(v, yaw);
                Location spot=location.clone().add(difference);
                map.put(spot, particles.get(vector));
            }
            return map;
        }
        /**
         * Get a map of locations & colors on which particles are to be displayed
         * @param location
         * @return
         */

        public Map<Location, Color> getParticles(Location location) {
            return getParticles(location, location.getPitch(), location.getYaw());
        }
       
       
        private void renderParticles(int sensitivity) {
            int height=image.getHeight();
            int width=image.getWidth();
            for(int x=0;x<width;x=x+sensitivity) {
                for(int y=0;y<height;y=y+sensitivity) {
                    int rgb=image.getRGB(x, y);
                    if(-rgb<=clearence)
                        continue;
                    java.awt.Color javaColor=new java.awt.Color(rgb);
                    Vector vector=new Vector((width-1)-x, (height-1)-y, 0);
                    particles.put(vector, Color.fromRGB(javaColor.getRed(),javaColor.getGreen(),javaColor.getBlue()));
                }
            }
        }
       
        private Vector rotateAroundAxisX(Vector v, double angle)
        {
            angle = Math.toRadians(angle);
            double y, z, cos, sin;
            cos = Math.cos(angle);
            sin = Math.sin(angle);
            y = v.getY() * cos - v.getZ() * sin;
            z = v.getY() * sin + v.getZ() * cos;
            return v.setY(y).setZ(z);
        }
        private Vector rotateAroundAxisY(Vector v, double angle)
        {
            angle = -angle;
            angle = Math.toRadians(angle);
            double x, z, cos, sin;
            cos = Math.cos(angle);
            sin = Math.sin(angle);
            x = v.getX() * cos + v.getZ() * sin;
            z = v.getX() * -sin + v.getZ() * cos;
            return v.setX(x).setZ(z);
        }

    }
     

    now to use this you need to have an image file(jpg, png etc)
    first you will load the image into your program as:
    Code (Java):
    public void onEnable() {
            File file=new File(getDataFolder(),"test.png"); //location of the image
            BufferedImage image = null;
            try {
                image=ImageIO.read(file);
               
            } catch (IOException e) {
                e.printStackTrace();
            }
           
           
        }
    now create an instance of the ImageParticles class like:
    Code (Java):
    ImageParticles particles=new ImageParticles(image,1);
        // 1 is the scanQuality higher the number lower the quality
    set the anchor point (height , width) & block/pixels ratio:
    Code (Java):
    //width = 50 , height = 10
        particles.setAnchor(50, 10);
        // 0.1 means 10 particles in a block
        particles.setDisplayRatio(0.1);
    now to get the locations on which particles need to be spawned use:
    Code (Java):

        //get the image on different orientation as that of the location
        Map<Location, Color> particle = particles.getParticles(location,pitch,yaw);
        //get the image on same orientation as that of the location
        Map<Location, Color> particle = particles.getParticles(location);
    now simply spawn particles on the locations with the corresponding color as:
    Code (Java):
    for(Location spot:particle.keySet()) {
                        Color color=particle.get(spot);
                        //spawn particle at location "spot" with color "color"
                        world.spawnParticle(Particle.REDSTONE,spot,1,color);
                    }
    Example:
    Since i was inspired by wings i thought of making wings using this resource as an example:

    Code (Java):
    public void onEnable() {
            File file=new File(getDataFolder(),"test.png");
            BufferedImage image = null;
            try {
                image=ImageIO.read(file);
               
            } catch (IOException e) {
                e.printStackTrace();
            }
           
            ImageParticles particles=new ImageParticles(image,1);
            particles.setAnchor(50, 10);
            particles.setDisplayRatio(0.1);

            Player player=Bukkit.getPlayer("backstabber");
            new BukkitRunnable()
            {
               
                @Override
                public void run() {
                    Vector dist = player.getEyeLocation().getDirection();
                    dist.multiply(-0.5);
                    Location location=player.getEyeLocation().add(dist).subtract(0,0.5,0);
                    Map<Location, Color> particle = particles.getParticles(location,25,location.getYaw());
                    for(Location spot:particle.keySet()) {
                        FastParticle.spawnParticle(player.getWorld(), ParticleType.REDSTONE,spot, 1, particle.get(spot));
                    }
                       
                   
                }
            }.runTaskTimerAsynchronously(this, 1, 5);
        }

    The image i created was:
    wing.JPG

    The result inside minecraft is:

    result.JPG

    Note:
    The image i used is not my property i just used it as an example. Credits goes to the author.
    also spawn particles async if you intend to heavily use this resource.
     
    • Like Like x 2
    • Informative Informative x 2
    • Useful Useful x 2
    • Friendly Friendly x 1
  2. So Useful, thanks for this tutorial!