12

I am trying to create a sprayer like effect when user touches the screen.

The user has the option of choosing a color, so the effect should be with the user's color choice.

How to implement that spray effect?

Vega
  • 27,856
  • 27
  • 95
  • 103
Raghunandan
  • 132,755
  • 26
  • 225
  • 256

4 Answers4

12

You'd just use the common draw part on the canvas... then specify a radius to be drawn to. Then using the 'random' function, draw (x) number of dots inside the area of the circle you defined using the radius for as long as the user is pressing down. If you need more exact help please let me know.

[Edit] This is going to be very pseudo-code. But you should very easily be able to make your code work from this.

// This needs to happen in the down press on the canvas
if(currentBrush == Brush.SPRAY_CAN){
    int dotsToDrawAtATime = 20;
    double brushRadius = 1.0; // This is however large they set the brush size, could be (1), could be whatever the max size of your brush is, e.g., (50), but set it based on what they choose

    for (int i = 0; i < dotsToDrawAtATime; i++){
        // Pick a random color for single dot to draw
        // Get the circumference of the circle (2*pi*brushRadius), based on the X/Y that the user input when they pressed down. Pick a random spot inside that area, and draw a single dot. As this is a for loop, it will happen 20 different times for this one occurrence.
    }
}

[Edit 2] If you're going to use this, I would highly consider incorporating Iain_b's way of doing this. Please take his post into consideration.

[Edit 3] Here's an image... maybe this will help you to understand...

enter image description here

[Edit 4]

Here's my code updated with lain_b's added part to help simplify it.

// This needs to happen in the down press on the canvas
if(currentBrush == Brush.SPRAY_CAN){
    int dotsToDrawAtATime = 20;
    double brushRadius = 1.0; // This is however large they set the brush size, could be (1), could be whatever the max size of your brush is, e.g., (50), but set it based on what they choose

    for (int i = 0; i < dotsToDrawAtATime; i++){
        // Pick a random color for single dot to draw
        ...

        // Get the location to draw to
        int x = touchedX + Random.nextGaussian()*brushRadius;
        int y = touchedY + Random.nextGaussian()*brushRadius;

        // Draw the point, using the random color, and the X/Y value
        ...
    }
}
RyanInBinary
  • 1,533
  • 3
  • 19
  • 47
  • private void touch_start(float x, float y) { mDrawingManager.mDrawingUtilities.mPath.reset(); mDrawingManager.mDrawingUtilities.mPath.moveTo(x, y); mX = x; mY = y; – Raghunandan Aug 13 '12 at 17:38
  • radius=mDrawingManager.mDrawingUtilities.mPaint.getStrokeWidth(); X,Y touch point on usertouch. So how do i calculate the the area in which i draw points using the X,Y as reference point?? – Raghunandan Aug 13 '12 at 18:02
  • I would use lain_b's method, and you won't have to worry about the circumference or area of the shape, it will handle that – RyanInBinary Aug 13 '12 at 18:22
  • The problem i am facing is getting the red area using x and y as the reference point. I know the radius and Circumference. – Raghunandan Aug 13 '12 at 18:27
  • 1
    Right. Using lain_b's method, the area and circumference no longer matter... it does the leg work for you. All you have to do is plugin the radius variable you're using to his formula. I updated my original post again, hopefully to add additional help – RyanInBinary Aug 13 '12 at 18:30
  • float radius=mDrawingManager.mDrawingUtilities.mPaint.getStrokeWidth(); Random rr = new Random(); float x1 = (float) (x + rr.nextGaussian()*radius); float y1 = (float) (y+ rr.nextGaussian()*radius); – Raghunandan Aug 13 '12 at 18:42
5

Hmm IMO logically I would:

  • have a spray can size/area/radius the user can choose from, when they touch the screen get the co-ordinates of the touch.

  • Then calculate the spray cans radius using the touched-point as the circles center.

  • Begin to draw/colour a certain amount of random pixels within the spray cans radius, (the longer the user holds over the same area/within the same radius, the greater the chance of filling the spot completely like a real spray can).

David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
3

This is an addition to the answers (DavidKroukamp , RyanInBinary)above I can't comment as I don't have enough repo. I would use a gaussian distribution for pixel distribution. Its much easier than it sounds :

int x = touchedX + Random.nextGaussian()*radius;
int y = touchedY + Random.nextGaussian()*radius;

Where TouchedX / Y is the location of the touch event ( and x ,y are the coordinates of a pixel to draw ). I just think it would give a more natural distribution. (Random -> java.util.Random)

David Kroukamp
  • 36,155
  • 13
  • 81
  • 138
Iain_b
  • 1,043
  • 5
  • 13
0

If performance is an issue, you can lazily cache the generated random values the first time then always reuse them. This has the added benefit of being able to undo/redo the same pseudo-random pattern, which might be useful in your app.

Andy
  • 1