ANDROID simulates the sliding jet effect of spark particles and android spark
Reprint please indicate this article from the blog of the big glutinous rice (http://blog.csdn.net/a396901990), thank you for your support!
Opening nonsense:
I changed my cell phone a year ago, SONY's Z3C. The mobile phone has a slide animation when unlocking the screen, similar to spark particle injection. The effect is dazzling...
As a result, I tried to simulate the effect after completion, as shown in (there are still many details not implemented ):
SurfaceView:
Because surfaceview is a dual-buffer mechanism, it is suitable for drawing images that require constant changes.
Next I copied several features about SurfaceView from the Internet (the source has been indicated), because one of the main purposes of writing this Demo is to familiarize myself with the Android plotting mechanism.
SurfaceView and View are essentially different:
Extracted from http://www.cnblogs.com/lipeil/archive/2012/08/31/2666187.html
SurfaceView can be re-painted in a new separate thread, and View must be updated in the main thread of the UI.
Updating the screen in the main UI thread may cause problems. For example, if you update the screen too long, your main UI thread will be blocked by the function you are painting. Then, messages such as buttons and touch screens cannot be responded.
When surfaceView is used to update the screen in a new thread, it will not block your main UI thread. But this also brings about another problem, that is, event synchronization. For example, if you touch the screen, you need to process the thread in surfaceView. Generally, you need an event queue design to save the touch event. This is a little more complicated because it involves thread synchronization.
Based on the above, the game features are generally divided into two categories:
1. passively update the image. For example, you can use view for chess. Because image update relies on onTouch for update, you can use invalidate directly. In this case, this Touch and the next Touch take a longer time and will not be affected.
2. Actively update. For example, a person is always running. This requires a separate thread to repeatedly repaint the state of the person, to avoid blocking the main UI thread. Obviously, the view is not suitable and needs surfaceView for control.
Double Buffering:
Extracted from http://blog.csdn.net/tobacco5648/article/details/8261749
When updating a view, SurfaceView in Android adopts a dual cache mechanism to improve update efficiency and enhance user experience.
Android official instructions:
Note: On each pass you retrieve the Canvas from the SurfaceHolder, the previous state of the Canvas will be retained. in order to properly animate your graphics, you must re-paint the entire surface. for example, you can clear the previous state of the Canvas by filling in a color with drawColor () or setting a background image with drawBitmap (). otherwise, you will see traces of the drawings you previusly completed MED.
Easy to understand:
It can be understood that SurfaceView uses two Canvas, one frontCanvas and one backCanvas when updating the view. Each time frontCanvas is displayed, backCanvas stores the view before the last change. When you use lockCanvas () to obtain the canvas, the result is actually the backCanvas instead of the frontCanvas being displayed, then you can draw a new view on the retrieved backCanvas, and then unlockCanvasAndPost (canvas) this view. Then, the uploaded canvas replaces the original frontCanvas as the new frontCanvas, the original frontCanvas will be switched to the background as the backCanvas. For example, if you have already drawn views A and B twice, you can call lockCanvas () to obtain the view. The result is A instead of B, after that, you will re-upload the C view, so C will replace B as the new frontCanvas displayed on SurfaceView, and the original B will be converted to backCanvas.
Surface usage:
(Extracted from http://www.cnblogs.com/devinzhang/archive/2012/02/03/2337559.html)
1) implementation steps
A. inherit SurfaceView
B. Implement the SurfaceHolder. Callback Interface
2) method to be rewritten
(1) public void surfaceChanged (SurfaceHolder holder, int format, int width, int height) {}// excitation when the surface size changes (2) public void surfaceCreated (SurfaceHolder holder) {}// triggered during creation. Generally, the drawing thread is called here. (3) public void surfaceDestroyed (SurfaceHolder holder) {}// triggered when the image is destroyed. Generally, the drawing thread is stopped and released here. </Span>
3) SurfaceHolder
SurfaceHolder, the surface controller, used to manipulate the surface. It processes effects and animations drawn on its Canvas, controls the surface, size, pixels, and so on. Several Methods to note:
(1) abstract void addCallback (SurfaceHolder. Callback callback); // send a Callback object to the current owner of SurfaceView. (2) abstract Canvas lockCanvas (); // lock the Canvas. After locking the Canvas, you can use the Canvas object returned by the Canvas to draw images on it. (3) abstract Canvas lockCanvas (Rect dirty); // draws a picture in a certain area of the Canvas. After the image is drawn, the unlockCanvasAndPost API is called to change the display content. // For games with relatively high memory requirements, you do not need to redraw pixels in other regions outside dirty to increase the speed. (4) abstract void unlockCanvasAndPost (Canvas canvas); // stop and lock the drawing and submit the changes. </Span>
4) summarize the entire process
Inherit SurfaceView and implement the SurfaceHolder. Callback interface ---->
SurfaceView. getHolder () Get the 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 and locks the drawing. Submit the changes to display the drawing.
Code implementation:
Before introducing the Code, let's sort out the following ideas:
1. Spark particles are continuously sprayed at finger clicks.
3. The longer the Particle Injection length and density are, the closer it is to the touch point, the less it is.
3. The particle will grow from small to disappear.
4. After a particle is generated, it will move randomly in a certain direction.
5. The particle will emit light and change the color.
Next we will explain it one by one:
1. Spark particles are continuously sprayed at finger clicks:
To process finger-pressing, you must first set the touch-click listener. The solution is to re-write the onTouchEvent method in the Custom surfaceview to obtain the click position of the finger.
When you know the touch points, you need to generate spark particles. In this case, you need to use Paint and Canvas to draw them.
Set the paint brush:
Private void setSparkPaint () {this. mSparkPaint = new Paint (); // open anti-aliasing this. mSparkPaint. setAntiAlias (true);/** set the Paint brush style to fill the 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 peripheral blur effect this. mSparkPaint. setMaskFilter (new BlurMaskFilter (BLUR_SIZE, BlurMaskFilter. blur. SOLID ));}
After the paint brush is set, use the paint brush to draw these particles on the canvas. In this case, particles are regarded as small dots. The function of the following method is to draw these circles cyclically at the touch points.
// Draw all sparks cyclically for (int [] n: sparks) {n = sparkManager. drawSpark (mCanvas, (int) X, (int) Y, n );}
After some column calculations, the canvas circle method is called to draw particles:
// Draw fireworks canvas. drawCircle (bezierPoint. x, bezierPoint. y, radius, mSparkPaint );
2. The longer the Particle Injection length and density are, the closer it is to the touch point, the less it is.
The length and density can be solved through the instant function.
mDistance = getRandom(SparkView.WIDTH / 4, mRandom.nextInt(15)) + 1;
3. The particle will grow from small to disappear:
I have tried to change the transparency of a particle based on its time, but the effect is not good.
Therefore, it is better to adjust the particle size directly. However, two phases are required:
In the first stage, the radius of the small circle of the particle ranges from 0 to the maximum.
In the second stage, the radius of the small circle of the particle ranges from the maximum to 0.
You only need to calculate the radius dynamically, and finally pass the radius to canvas. drawCircle to achieve this effect.
Because the radius value needs to be increased evenly, my idea is to multiply the ratio of the path length to the current walking length by a rate:
/*** Update spark path */private void updateSparkPath () {mCurDistance + = PER_SPEED_SEC; // The first half if (mCurDistance <(mDistance/2) & (mCurDistance! = 0) {radius = SPARK_RADIUS * (mCurDistance/(mDistance/2);} // The second half else if (mCurDistance> (mDistance/2) & (mCurDistance <mDistance) {radius = SPARK_RADIUS-SPARK_RADIUS * (mCurDistance/(mDistance/2)-1 );} // complete else if (mCurDistance> = mDistance) {mCurDistance = 0; mDistance = 0; radius = 0 ;}}
4. After a particle is generated, it will move randomly in a certain direction.
This is simple. I believe everyone can think of it --SABEL Curve(For more information, see wikipedia ).
The particle path can be simulated by a 4-point saabel curve, for example:
I found a function on the Internet to find the point of the bell curve in a certain time ratio:
/*** Calculate the sebel curve ** @ param t time, range: 0-1 * @ param s start point * @ param c1 inflection point 1 * @ param c2 inflection point 2 * @ param e endpoint * @ return the point of the sebel curve at the current time */ private Point CalculateBezierPoint (float t, point s, Point c1, Point c2, Point 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 calculated vertex to the circle function:
// Calculate the current Point of the sebel curve. Point bezierPoint = CalculateBezierPoint (mCurDistance/mDistance, start, c1, c2, end); // draw a fireworks canvas. drawCircle (bezierPoint. x, bezierPoint. y, radius, mSparkPaint );
5. The particle will emit light and change the color.
The light emitting and changing colors are both set through the paint brush:
Light glow:
this.mSparkPaint.setMaskFilter(new BlurMaskFilter(BLUR_SIZE, BlurMaskFilter.Blur.SOLID));
However, hardware acceleration must be disabled:
// Disable hardware acceleration setLayerType (LAYER_TYPE_SOFTWARE, null );
Set the random color change:
// Set the random color mSparkPaint. setColor (Color. argb (255, mRandom. nextInt (128) + 128, mRandom. nextInt (128) + 128, mRandom. nextInt (128) + 128 ));
Summary:
The general logic has been introduced, and many details have not been implemented, and some flashes have been found, but no good solutions have been found (please kindly advise )...
Github download link:
Https://github.com/a396901990/SparkScreen/tree/master
The last two articles about SurfaceView and drawing are recommended:
If you use SurfaceVIew to play gamesCreate a SurfaceView Game step-by-step
Elder brother'sAndroid custom controls are actually very simpleSeries