Android實現煙花效果

jopen 9年前發布 | 10K 次閱讀 Java Android

HolderSurfaceView.java

package com.lyc;

import android.graphics.PixelFormat; import android.view.SurfaceView;

public class HolderSurfaceView { private HolderSurfaceView() {

}
private SurfaceView mSurfaceView;
private static HolderSurfaceView mHolderSurfaceView = null;

public static HolderSurfaceView getInstance() {
    if (mHolderSurfaceView == null)
        mHolderSurfaceView = new HolderSurfaceView();
    return mHolderSurfaceView;
}



public void setSurfaceView(SurfaceView view) {
    mSurfaceView = view;
    mSurfaceView.setZOrderOnTop(true);
    mSurfaceView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}

public SurfaceView getSurfaceView() {
    return mSurfaceView;
}

}

DrawTopBase.java

package com.lyc;

import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.PorterDuff.Mode; import android.graphics.PorterDuffXfermode; import android.graphics.Rect; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceHolder.Callback; import android.view.SurfaceView; import android.view.View; import android.view.View.OnTouchListener;

public class DrawTopBase implements Runnable, Callback ,OnTouchListener{

protected DrawStatus mStatus = DrawStatus.NoWork; protected SurfaceView mSurfaceView; protected SurfaceHolder mSurfaceHolder; protected Context mContext; protected Rect mSurfaceRect = new Rect(0, 0, 0, 0); //前兩個參數是左上角的坐標,后兩個參數是右下角的坐標(不是寬度和高度)

public DrawTopBase() {
    setSurfaceView(HolderSurfaceView.getInstance().getSurfaceView());
}

public void setSurfaceView(SurfaceView view) {
    mSurfaceView = view;
    mContext = mSurfaceView.getContext();
    mSurfaceHolder = mSurfaceView.getHolder();
    mSurfaceHolder.addCallback(this);

// mSurfaceRect.set(new Rect(0, 0, mSurfaceView.getWidth(), mSurfaceView.getHeight())); mSurfaceRect.set(new Rect(100, 100, 250, 250)); set(); }

public void set() {
    setRect(mSurfaceRect);
}

protected Thread mThread = null;


public void begin() {

    if (mThread == null) {
        mThread = new Thread(this);
        mThread.start();

    }
}

public void end() {
    mStatus = DrawStatus.Ending;
}


protected void doWork(Canvas canvas) {

}


protected void endWork() {

}

protected Paint mPaint = new Paint();


protected void clear(Canvas canvas) {
    mPaint.setXfermode(new PorterDuffXfermode(Mode.CLEAR));
    canvas.drawPaint(mPaint);
    mPaint.setXfermode(new PorterDuffXfermode(Mode.SRC));
}

protected void clear() {
    synchronized (mSurfaceHolder) {
        Canvas canvas = this.mSurfaceHolder.lockCanvas();
        try {
            clear(canvas);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (canvas != null)
                mSurfaceHolder.unlockCanvasAndPost(canvas);
        }
    }
}

protected void doChange() {
    change();
}


protected void change() {

}

// protected Rect mRect = new Rect(0, 0, 0, 0); protected Rect mRect = new Rect(50, 50, 250, 250);

public void setRect(Rect r) {
    mRect.set(r);
}

public Rect getRect() {
    return mRect;
}




protected enum DrawStatus {
    NoWork, Drawing, Ending, Destroyed
};

protected long mBegintime;

public void run() {
    mStatus = DrawStatus.Drawing;
    //獲取當前時間
    starttime = System.currentTimeMillis();
    mBegintime = System.currentTimeMillis();
    // 建立兩次緩存
    clear();
    clear();
    while (mStatus == DrawStatus.Drawing) {
        synchronized (mSurfaceHolder) {
            Canvas canvas = this.mSurfaceHolder.lockCanvas(getRect());
            try {
                if (canvas != null) {
                    clear(canvas);
                    doWork(canvas);
                }
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (canvas != null)
                    mSurfaceHolder.unlockCanvasAndPost(canvas);
            }
            doChange();               
        }
        calculatePerframe();
    }
    if (mStatus != DrawStatus.Destroyed)
        clear();
    mThread = null;
    endWork();
}


protected long starttime;
// 每幀時間 60幀附近 第一次計算前使用 毫秒
private float perframe = 6;   //6=16

private int count = 0;

// 每隔多長時間測試一次幀時間
private int mRefreshSpeed = 30; //30=12

// 設定要求多長時間每幀 24幀每秒
private float mFPS = 1000 / 4;
private float sleep = mFPS;

// 設置刷新頻率
public void setFPS(int fps) {
    mFPS = 1000 / fps;
}


protected void calculatePerframe() {
    count++;
    if (count == mRefreshSpeed) // 由于每幀計算會降低游戲效率。20到50差不多
    {
        long timepass = System.currentTimeMillis();
        long time = timepass - starttime;
        perframe = time / mRefreshSpeed;// 每幀時間
        sleep = perframe > mFPS ? mFPS - (perframe - mFPS) / mRefreshSpeed : mFPS;
        starttime = timepass;
        count = 0;
    }
    try {

        Thread.sleep((long) (sleep));

// Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } // new Thread(){ // public void run(){ // try { //
// sleep(2000); // } catch (Exception e) { // // TODO: handle exception // e.printStackTrace(); // }finally{ //// finish(); // } // } // }.start();

}

public void surfaceChanged(SurfaceHolder holder, int format, int width,
        int height) {
    mSurfaceRect.set(new Rect(0, 0, width, height));

// mSurfaceRect.set(new Rect(0, 0, 200, 500)); set(); }

public void surfaceCreated(SurfaceHolder holder) {

}

public void surfaceDestroyed(SurfaceHolder holder) {
    mStatus = DrawStatus.Destroyed;
}

public boolean onTouch(View v, MotionEvent event) {
    // TODO Auto-generated method stub
    return false;
}

}

package com.lyc;

import java.util.Random;

import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Rect; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.View;

public class DrawYH extends DrawTopBase {

private int m_nAppX; private int m_nAppY; private int m_centerX; private int m_centerY; private int m_mouseX; private int m_mouseY; private int m_sleepTime; private boolean isError; private boolean m_isPaintFinished; boolean isRunning; boolean isInitialized; Thread runner; int pix0[]; Bitmap offImage; // Image dbImg; int pixls; int pixls2; Random rand; int bits; double bit_px[]; double bit_py[]; double bit_vx[]; double bit_vy[]; int bit_sx[]; int bit_sy[]; int bit_l[]; int bit_f[]; int bit_p[]; int bit_c[]; int bit_max = 100; // int bit_sound = 2; int ru; int rv; @Override public void surfaceCreated(SurfaceHolder holder) { // TODO Auto-generated method stub super.surfaceCreated(holder); this.begin(); // stopBGMedia(); // bgMedia = new GameSoundMedia(mContext); // bgMedia.playInMediaPlayer(R.raw.bg, null); }

// private void stopBGMedia() { // if (bgMedia != null) { // try { // bgMedia.stopAll();
// bgMedia = null; // } catch (Exception e) { // e.printStackTrace(); // } // // } // }

@Override
public void surfaceDestroyed(SurfaceHolder holder) {

// stopBGMedia(); super.surfaceDestroyed(holder); }

@Override
public void set() {
    super.set();
    if (this.getRect().width() > 10 && this.getRect().height() > 10)
        init();
}



Draw.java //重要類

public Draw() {     //畫煙花
    super();
    m_mouseX = 0;
    m_mouseY = 0;
    m_sleepTime = 5;   //5
    isError = false;
    isInitialized = false;
    rand = new Random();
    bits = 10000;           //控制煙花數量
    bit_px = new double[bits];
    bit_py = new double[bits];
    bit_vx = new double[bits];
    bit_vy = new double[bits];
    bit_sx = new int[bits];
    bit_sy = new int[bits];
    bit_l = new int[bits];
    bit_f = new int[bits];
    bit_p = new int[bits];
    bit_c = new int[bits];
    ru = 50;
    rv = 50;
    // init();
}

Canvas mCanvas;
private Rect drawRect = new Rect(0, 0, 0, 0);

public void init() {


    m_nAppX = this.getRect().width() / 2;
    m_nAppY = this.getRect().height() / 2;
    drawRect = new Rect(0, 0, m_nAppX, m_nAppY);
    m_centerX = m_nAppX / 2;
    m_centerY = m_nAppY / 2;
    m_mouseX = m_centerX;
    m_mouseY = m_centerY;
    // resize(m_nAppX, m_nAppY);
    pixls = m_nAppX * m_nAppY;
    pixls2 = pixls - m_nAppX * 3;
    pix0 = new int[pixls];
    offImage = Bitmap.createBitmap(m_nAppX, m_nAppY,
            Bitmap.Config.ARGB_8888);
    mCanvas = new Canvas();
    mCanvas.setBitmap(offImage);
    for (int i = 0; i < pixls; i++)
        pix0[i] = 0xff000000;

    for (int j = 0; j < bits; j++)
        bit_f[j] = 0;

    isInitialized = true;
}

@Override
protected void doWork(Canvas canvas) {
    // TODO Auto-generated method stub
    super.doWork(canvas);
    if (offImage != null)
        canvas.drawBitmap(offImage, drawRect, this.getRect(), mPaint);

}

@Override
protected void change() {
    super.change();
    if (isInitialized) {
        for (int j = 0; j < pixls2; j++) {     //pixls=pixls2
            int k = pix0[j];
            int l = pix0[j + 1];
            int i1 = pix0[j + m_nAppX];
            int j1 = pix0[j + m_nAppX + 1];
            int i = (k & 0xff0000) >> 16;
            int k1 = ((((l & 0xff0000) >> 16) - i) * ru >> 8) + i;
            i = (k & 0xff00) >> 8;
            int l1 = ((((l & 0xff00) >> 8) - i) * ru >> 8) + i;
            i = k & 0xff;
            int i2 = (((l & 0xff) - i) * ru >> 8) + i;
            i = (i1 & 0xff0000) >> 16;
            int j2 = ((((j1 & 0xff0000) >> 16) - i) * ru >> 8) + i;
            i = (i1 & 0xff00) >> 8;
            int k2 = ((((j1 & 0xff00) >> 8) - i) * ru >> 8) + i;
            i = i1 & 0xff;
            int l2 = (((j1 & 0xff) - i) * ru >> 8) + i;
            int i3 = ((j2 - k1) * rv >> 8) + k1;
            int j3 = ((k2 - l1) * rv >> 8) + l1;
            int k3 = ((l2 - i2) * rv >> 8) + i2;
            pix0[j] = i3 << 16 | j3 << 8 | k3 | 0x77000000;
            // if(pix0[j]==0x77000000)pix0[j]=0x55000000;
        }

        rend();

        mCanvas.drawBitmap(pix0, 0, m_nAppX, 0, 0, m_nAppX, m_nAppY, true,mPaint);
    }
}

public void dot() {
    dot(rand.nextInt(m_nAppX), rand.nextInt(m_nAppY));
}

public void dot(int x, int y) {
    m_mouseX = x;
    m_mouseY = y;
    int k = (int) (rand.nextDouble() * 256D);
    int l = (int) (rand.nextDouble() * 256D);
    int i1 = (int) (rand.nextDouble() * 256D);
    int j1 = k << 16 | l << 8 | i1 | 0xff000000;
    int k1 = 0;
    for (int l1 = 0; l1 < bits; l1++) {
        if (bit_f[l1] != 0)
            continue;
        bit_px[l1] = m_mouseX;
        bit_py[l1] = m_mouseY;
        double d = rand.nextDouble() * 6.2800000000000002D;
        double d1 = rand.nextDouble();
        bit_vx[l1] = Math.sin(d) * d1;
        bit_vy[l1] = Math.cos(d) * d1;
        bit_l[l1] = (int) (rand.nextDouble() * 100D) + 100;
        bit_p[l1] = (int) (rand.nextDouble() * 3D);
        bit_c[l1] = j1;
        bit_sx[l1] = m_mouseX;
        bit_sy[l1] = m_nAppY - 5;
        bit_f[l1] = 2;
        if (++k1 == bit_max)
            break;
    }
}

void rend() {
    boolean flag = false;
    boolean flag1 = false;
    boolean flag2 = false;
    for (int k = 0; k < bits; k++)
        switch (bit_f[k]) {

        case 1: // '\001'
            bit_vy[k] += rand.nextDouble() / 50D;
            bit_px[k] += bit_vx[k];
            bit_py[k] += bit_vy[k];
            bit_l[k]--;
            if (bit_l[k] == 0 || bit_px[k] < 0.0D || bit_py[k] < 0.0D
                    || bit_px[k] > (double) m_nAppX
                    || bit_py[k] > (double) (m_nAppY - 3)) {
                bit_c[k] = 0xff000000;
                bit_f[k] = 0;
            } else if (bit_p[k] == 0) {
                if ((int) (rand.nextDouble() * 2D) == 0)
                    bit_set((int) bit_px[k], (int) bit_py[k], -1);
            } else {
                bit_set((int) bit_px[k], (int) bit_py[k], bit_c[k]);
            }
            break;

        case 2: // '\002'
            bit_sy[k] -= 5;
            if ((double) bit_sy[k] <= bit_py[k]) {
                bit_f[k] = 1;
                flag2 = true;
            }
            if ((int) (rand.nextDouble() * 20D) == 0) {
                int i = (int) (rand.nextDouble() * 2D);
                int j = (int) (rand.nextDouble() * 5D);
                bit_set(bit_sx[k] + i, bit_sy[k] + j, -1);
            }
            break;
        default:
            break;

        }

// if (flag2 && bit_sound > 0) // sm.playInMediaPlayer(R.raw.firework, null); // soundPool.play(id_sound1, 0); }

void bit_set(int i, int j, int k) {
    int l = i + j * m_nAppX;
     pix0[l] = k;
}

protected void calculatePerframe() {
      try {
        Thread.sleep(m_sleepTime);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}



@Override
public boolean onTouch(View v, MotionEvent event) {
    // return super.onTouch(v, event);
    int x = (int) event.getX();
    int y = (int) event.getY();
    x = x / 2;
    y = y / 2;
    if (x > m_nAppX)
        x = m_nAppX;
    if (y > m_nAppY)
        y = m_nAppY;
    if (x < 0)
        x = 0;
    if (y < 0)
        y = 0;
    switch (event.getAction()) {

// case MotionEvent.ACTION_DOWN: // // break; // case MotionEvent.ACTION_UP: // this.dot(x, y); // if (this.bit_sound > 1) // sm.playInMediaPlayer(R.raw.syu, null); // soundPool.play(id_sound2, 0); // break; case MotionEvent.ACTION_MOVE: this.dot(x,y); break; } m_mouseX = x; m_mouseY = y; return true; } }

package com.lyc;

import android.app.Activity; import android.os.Bundle; import android.view.SurfaceView;

public class MainActivity extends Activity {

public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // setContentView(R.layout.main); SurfaceView v = new SurfaceView(this); // bt1 = (Button) findViewById(R.id.bt1); HolderSurfaceView.getInstance().setSurfaceView(v); // v.setBackgroundResource(R.drawable.mov005); this.setContentView(v); final DrawYH yh=new DrawYH();
v.setOnTouchListener(yh); yh.begin();

} }</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!