Reprint Please indicate this article from Big Corn's blog (http://blog.csdn.net/a396901990 ), thank you for your support!
Opening nonsense:
A mobile phone was changed a year ago, Sony's z3c. The phone has a sliding animation when unlocking the screen, a spark-like particle spray that's very cool ...
So try to simulate a bit, after the finished effect such as (there are many details not implemented ):
Surfaceview:
Because the Surfaceview is a double-buffering mechanism, it is suitable for drawing this kind of picture that needs to be changed constantly.
Here I copy a few features from the web about Surfaceview (which has been shown) because one of the main purposes of writing this demo is to familiarize yourself with the graphics mechanism of Android.
The most essential differences between Surfaceview and view:
Excerpt from http://www.cnblogs.com/lipeil/archive/2012/08/31/2666187.html
Surfaceview is the ability to redraw the screen in a new, separate thread, and view must update the screen in the main thread of the UI.
Updating the screen in the main thread of the UI may cause problems, such as the time you update the screen too long, and your main UI thread will be blocked by the function you are drawing. Then you will not be able to respond to keystrokes, touch screens and other messages.
When using Surfaceview because it is updating the screen in a new thread, it does not block your UI main thread. But this also brings up another problem, namely, the synchronization of events. For example, if you touch the screen, you need to surfaceview in the thread processing, it is generally necessary to have an event queue design to save touch event, which is slightly more complicated, because it involves thread synchronization.
Therefore, based on the above, according to the characteristics of the game, generally divided into two categories:
1 Passive Update screen. Like chess, this is good with view. Because the screen update is dependent on OnTouch to update, you can use the invalidate directly. Because of this, the touch and the next touch will take longer and will not have an impact.
2 active updates. Like a man running all the time. This requires a separate thread to redraw the human state continuously, avoiding blocking the main UI thread. So obviously the view is not suitable, need surfaceview to control.
Double buffering:
Excerpt from http://blog.csdn.net/tobacco5648/article/details/8261749
Surfaceview in Android updates the view to improve the efficiency of the update and enhance the user experience, using a dual-cache mechanism.
Official Description of Android:
Note:on each pass you retrieve the canvas from the Surfaceholder, the previous state of the canvas would be retained. In order to properly animate your graphics, you must re-paint the entire surface. For example, your can clear the previous state of the Canvas by filling in a color with drawcolor () or setting a background Image with Drawbitmap (). Otherwise, you'll see traces of the drawings you previously performed.
Simple to understand:
It can be understood as: Surfaceview uses two canvases, one frontcanvas and one backcanvas to update the view, and each time it actually shows that the Frontcanvas,backcanvas is storing the view before the last change. When using Lockcanvas () to get the canvas, you get the actual backcanvas instead of the Frontcanvas being displayed, and then you draw a new view on the Backcanvas that you get. Again Unlockcanvasandpost (canvas) This view, then upload this canvas will replace the original Frontcanvas as the new Frontcanvas, the original Frontcanvas will switch to the background as Backcanvas. For example, if you have already drawn views A and B two times, then you call Lockcanvas () to get the view, get a instead of the B that is being displayed, and then you say redraw the C view to upload, then C will replace B as the new Frontcanvas display on the Surfaceview , the original B is converted to Backcanvas.
How to use your surface:
(Excerpt from http://www.cnblogs.com/devinzhang/archive/2012/02/03/2337559.html)
1) Implementation steps
A Inherit Surfaceview
b Implementing the Surfaceholder.callback Interface
2) methods that need to be rewritten
(1) public void surfacechanged (Surfaceholder holder,int format,int width,int height) {}//fires when the size of surface changes (2) public void surfacecreated (Surfaceholder holder) {}//fires at creation time, which is typically called the paint thread here. (3) public void surfacedestroyed (Surfaceholder holder) {}//Fires when destroyed, typically here the drawing thread is stopped, released. </span>
3) Surfaceholder
The Surfaceholder,surface controller is used to manipulate surface. Handle it on canvas to draw effects and animations, control surfaces, sizes, pixels, etc. Several methods to be aware of:
(1), abstract void Addcallback (Surfaceholder.callback Callback);//give Surfaceview the current holder a callback object. (2), abstract canvas Lockcanvas ();//Lock the canvas, usually after the lock can be used to return the canvas objects, such as painting on top of canvas, and so on. (3), abstract canvas Lockcanvas (Rect dirty);//Lock a region of the canvas for drawing, etc... Since the drawing is finished, the following unlockcanvasandpost will be called to change the display. Compared to some of the higher memory requirements of the game, you can not redraw the dirty outside the pixels of other areas, can improve speed. (4), abstract void unlockcanvasandpost (canvas canvas);//End lock drawing and commit changes. </span>
4) Summarize the process
Inherit Surfaceview and implement Surfaceholder.callback interface---->
Surfaceview.getholder () Get Surfaceholder object---->
Surfaceholder.addcallback (callback) Add callback function---->
Surfaceholder.lockcanvas () Get the canvas object and lock the canvas---->
Canvas painting---->
Surfaceholder.unlockcanvasandpost (canvas canvas) ends the lock drawing and commits the change to display the graphic.
Code implementation:
Before introducing the code, let's start with a simple idea:
1. The spark particles will be sprayed at the point where the finger is clicked.
3. Particle jet length and density are different, the closer to the touch point, the farther the less
3. The particles will grow from small to large, and then disappear.
4. The particles will move randomly in one direction after they are produced.
5. The particles will have a faint glow effect and will change color
Here are some explanations:
1. The spark particles will be sprayed at the point where the finger is clicked:
To handle a finger press the first thing you need to set up touch-click snooping is to override the Ontouchevent method in your custom Surfaceview to get the click position of your finger.
When you know the touch point, you need to create a spark particle, and you need to use a brush (paint) and an artboard (canvas) to draw them.
To set the Brush method:
private void Setsparkpaint () { this.msparkpaint = new Paint (); Turn on anti-aliasing This.mSparkPaint.setAntiAlias (true); / * * Set brush style to fill Paint.Style.STROKE: stroke Paint.Style.FILL_AND_STROKE: Stroke and fill * Paint.Style.FILL: Fill */ This.mSparkPaint.setDither (true); This.mSparkPaint.setStyle (Paint.Style.FILL); Set the perimeter blur effect this.mSparkPaint.setMaskFilter (new Blurmaskfilter (Blur_size, BlurMaskFilter.Blur.SOLID)); }
After the brush is set up, use this brush to draw these particles on the canvas, and the particles are considered as small dots for simplicity. The function of the following method is to draw these small circles in the touch point loop
Loop draws all sparks for (int[] n:sparks) { n = Sparkmanager.drawspark (Mcanvas, (int) X, (int) Y, n); }
After some column calculations, call canvas to draw a circle to draw the particles:
Painted Flower Fire canvas.drawcircle (bezierpoint.x, Bezierpoint.y, radius, msparkpaint);
2. Particle jet length and density are different, the closer to the touch point, the farther the less
The length, and density of these two can be solved by the function immediately.
Mdistance = Getrandom (SPARKVIEW.WIDTH/4, Mrandom.nextint (15)) + 1;
3. Particles grow from small to large and disappear from the largest:
Previous attempts to change the transparency based on particle presence time have not been effective.
So it's better to adjust the particle size directly. However, two phases are required:
In the first stage, the radius of the particle small circle is from 0 to maximum.
In the second stage, the radius of the particle's small circle is from maximum to 0.
You only need to calculate the radius dynamically, and finally pass the radius to the canvas.drawcircle to complete the effect.
because the value of the RADIUS needs to be increased evenly, my idea is to multiply the ratio of path length and current traversed length by one rate:
/** * Update spark path * /private void Updatesparkpath () { mcurdistance + = per_speed_sec; First half if (Mcurdistance < (MDISTANCE/2) && (mcurdistance! = 0)) { radius = Spark_radius * (mcurdi Stance/(MDISTANCE/2)); } The second half segment else if (Mcurdistance > (MDISTANCE/2) && (Mcurdistance < mdistance)) { radius = SPAR K_radius-spark_radius * ((Mcurdistance/(MDISTANCE/2))-1); } Complete the else if (mcurdistance >= mdistance) { mcurdistance = 0; mdistance = 0; Radius = 0; } }
4. The particles will move randomly in one direction after they are produced.
This is simple, I believe you can certainly think of IS- Seibel curve (about Seibel curve recommended reference Wikipedia).
The particle path can be simulated by a 4-point Seibel curve, such as:
I found a function on the Internet to find the point at which the Bell curve is at a certain time:
/** * Calculate plug Belle curve * * @param t time, range 0-1 * @param s start point * @param C1 inflection 1 * @param c2 inflection 2 * @param e End * @return The dots at the current time * /Private point calculatebezierpoint (float T, points s, C1 e) { float u = 1-t; Float TT = t * t; float UU = u * U; float UUU = UU * U; float TTT = tt * t; Point P = new Point ((int) (s.x * UUU), (int) (S.Y * UUU)); p.x + = 3 * UU * t * c1.x; P.Y + = 3 * UU * t * C1.Y; p.x + = 3 * U * TT * c2.x; P.Y + = 3 * U * TT * C2.Y; p.x + = TTT * e.x; P.Y + = TTT * E.Y; return p; }
Pass the computed point into the circle function:
Calculates the current point of the plug-belle curve bezierpoint = Calculatebezierpoint (mcurdistance/mdistance, start, C1, c2, end); Painted Flower Fire canvas.drawcircle (bezierpoint.x, Bezierpoint.y, radius, msparkpaint);
5. The particles will have a faint glow effect and will change color
The faint glow and transform colors are set by the brush:
Faint Glow:
This.mSparkPaint.setMaskFilter (New Blurmaskfilter (Blur_size, BlurMaskFilter.Blur.SOLID));
but hardware acceleration needs to be turned off:
Turn off hardware acceleration setlayertype (layer_type_software, NULL);
Set the random transform color:
Set Random color msparkpaint.setcolor (Color.argb (255, Mrandom.nextint (+) +, Mrandom.nextint (128) + 128, Mrandom.nextint (128) + 128));
Summarize:
The general logic has been introduced, there are many details did not realize, and found a slight flicker phenomenon, but did not find a good solution (for the big God) ...
Github Download Connection:
Https://github.com/a396901990/SparkScreen/tree/master
Finally, two articles on Surfaceview and drawing are recommended:
If the game is done through Surfaceview Create a surfaceview Game step-by-step
Aigo's Android custom controls are actually very simple series
Android simulated spark particle's slide spray effect