4

I am currently trying to make a rainbow trail that follows your mouse. i used Linkedlist to plot the points of my mouse so the trail follows along. The trail itself looks perfect its only the colors in the trail that don't look right. I'm wanting them to fade into each other. Someone told me to use linear interpolation and after looking into it for awhile it seems like it would work i just don't know how to implement it.

this is the code i have so far:

import impsoft.bots.ColorBot;
import impsoft.scripting.ibot.interfaces.AutoPaint;
import impsoft.scripting.types.ColorScript;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.Deque;
import java.util.LinkedList;

import impsoft.scripting.ibot.structs.XY;
import impsoft.scripting.types.ColorSkeltonScriptable;
import impsoft.scripting.types.parallel.scriptjobs.ScriptJob;


public class MouseTrail extends ColorScript implements AutoPaint {
     public MouseTrail(ColorBot c) {
      super(c);

     }
    public void script() throws InterruptedException {
     while(true) {
         mt.setSize(500);
         mt.exec();

      sleep(100);
     }
    }

    public static String name = "Mouse trail test";
    public static String author = "Llaver";
    public static String description = "test for mouse trail";
    public static double version = 1.00;


public class MouseTrail2 extends ScriptJob implements AutoPaint {


    private int size;
    private final ColorSkeltonScriptable cs;
    private final Deque<XY> trail = new LinkedList<XY>();
    private final Color[] rainbow = new Color[]{
            Color.RED, Color.YELLOW, Color.GREEN, Color.CYAN, Color.BLUE, Color.magenta
        };

    public MouseTrail2(ColorSkeltonScriptable cs) {
        super(cs);
        this.cs = cs;
    }

    public void setSize(int s) {
        size = s;
        s = 200;
    }

    public void runV() {
        try {
            while (true) {

                synchronized (trail) {
                    if (trail.size() >= size) {
                        trail.pop();
                    }
                    trail.offer(cs.getCurrentMouseXY());
                }
                sleep(1);
            }

        } catch (InterruptedException e) {
        }
    }

    @Override
    public void paint(Graphics g) {
        final Graphics2D g2d = (Graphics2D) g;
        g2d.setStroke(new BasicStroke(3, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
        g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        synchronized (trail) {
                float perc;
                int idx;
                for(int i = 1 ; i < trail.size() - 1 ; i++){
        XY current = ((LinkedList<XY>) trail).get(i);
        XY next = ((LinkedList<XY>) trail).get(i - 1);
        perc = ((float)i / trail.size()) * 100f;
       idx = Math.round((perc * (float)rainbow.length) / 100f);
       if(idx >= rainbow.length)idx -= 1;       
       g2d.setColor(rainbow[idx]);
        g.drawLine(current.x, current.y, next.x, next.y);
    }
            }
        }

    }


@Override
public void paint(Graphics arg0) {  
}
private MouseTrail2 mt = new MouseTrail2(this);

}

some pics:

this is what i have right now:

http://img11.imageshack.us/img11/3031/mousetrailhavenow.png

this is what im trying to get:

http://img594.imageshack.us/img594/7381/mousetrailtryingtoget.png

does that possibly make this a little more clear?

Ryan - Llaver
  • 528
  • 4
  • 19
  • when i try that the trails color depends on its location on the screen instead of where it is in the trail following behind it. i need it so it can get points from the LinkedList and base its color upon that.. if that makes sense – Ryan - Llaver Sep 14 '11 at 23:02
  • Anything you can use [here](http://stackoverflow.com/questions/6992633/painting-the-slider-icon-of-jslider/6996263#6996263)? – trashgod Sep 15 '11 at 00:21
  • no not much =/ I've already tried lineargradientpaint but it doesnt work how i would need it too. it makes a box instead of following specified points – Ryan - Llaver Sep 15 '11 at 02:07
  • I added some pics to show what I'm trying to do if that makes things a little more clear – Ryan - Llaver Sep 15 '11 at 15:40
  • haha i finally got it by just messing around. turns out it was a lot simpler than i thought and i just had to use the length of my linkedlist in a formula and that gave me all the colors i needed((: thanks for the help((: – Ryan - Llaver Sep 16 '11 at 07:08
  • 2
    Why not update your question or add an answer with your revised code? – trashgod Sep 16 '11 at 14:27

1 Answers1

3

To get the effect you want, you are probably going to have to create a custom gradient paint that spans the gamut of hue along one axis and the range of alpha transparency along the other. As a related example, this KineticModel uses a RadialGradientPaint to create an array of GradientImage instances. In each image, the alpha varies radially from 0xff (1.0) at the center to 0x3f (0.25) at the periphery.

Addendum: Based on your picture, just set the graphics context's Stroke to a suitable width, set the paint to the next hue from your color lookup table (clut), and drawLine(). You can vary the hue, keeping the the saturation and brightness constant.

float N = 360;
Queue<Color> clut = new LinkedList<Color>();
for (int i = 0; i < N; i++) {
    clut.add(Color.getHSBColor(i / N, 1, 1));
}

You'll have to decide when to change colors based on space or time. For the latter, javax.swing.Timer is a good choice.

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • meh wasnt your code but it made me think and helped me find the answer so ill do it anyways(: it was actually a lot simpler then what you posted lol – Ryan - Llaver Sep 16 '11 at 16:03
  • Sounds like it might make a good answer; ping me if you post it. Something like `clut.add(clut.remove())` effectively rorates teh lookup table. – trashgod Sep 16 '11 at 16:12