WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

ライブ壁紙を作ってみる

こんにちは
今回エンジニアブログを担当させて頂きます、佐藤です。

先日、Androidでライブ壁紙を作ってみたいと思ったので
今回はライブ壁紙について調べたことをまとめてみました!

◆ライブ壁紙とは

ライブ壁紙とは、ホーム画面で動くアプリケーションのようなものです。

非常に一般的なアプリケーションと似ていて、タッチ判定、加速度センサー、GPS、ネットワークアクセス等の機能を使用することも可能です。

GooglePlayでも様々なデザインや機能のライブ壁紙があります。

◆アプリとの違い

一般的なのアプリケーションとの大きな違いは、

作成時にActivityクラスではなくWallpaperServiceの継承をすること

onCreateEngine()メソッドの追加をすることです。

このメソッドはライブ壁紙作成する際に呼び出されます。

描画を行うためのクラスを自作し、そのクラスのコンストラクタを返します。

◆簡単なサンプルを作成

簡単なサンプルを作成してみました。

public class SampleLiveWall extends WallpaperService {  
  
    private final Handler mHandler = new Handler();  
  
    @Override  
    public Engine onCreateEngine() {
        // 描画用の自作Engineクラス  
        return new LiveEngine();
    }  
  
    // 描画を行うEngineクラス  
    public class LiveEngine extends Engine {
        // 画像  
        private Bitmap image;  
  
        //---移動関連-------------------  
        //x  
        private int x = 0;
        //y  
        private int y = 0;
        //速度X  
        private int speedX = 20;
        //速度Y  
        private int speedY = 20;
        //幅  
        private int width;
        //高さ  
        private int height;
        // 画像のパス  
        private int[] imgPath = {R.drawable.img1, R.drawable.img2, R.drawable.img3, R.drawable.img4};
        // ランダムで画像を変える  
        private Random rand;  
  
        // 描画用のRunnable  
        private final Runnable drawRunnable = new Runnable() {  
            public void run() {  
                drawFrame();  
            }
        };  
  
        //表示状態  
        private boolean visible;  
  
        //====== コンストラクタ ===========//  
        public LiveEngine() {
            rand = new Random();
            image = BitmapFactory.decodeResource(getResources(), imgPath[rand.nextInt(4)]);
        }  
  
        //====== 生成時に呼び出される ===========//  
        @Override  
        public void onCreate(SurfaceHolder surfaceHolder) {
            super.onCreate(surfaceHolder);
        }  
  
        //====== 破棄時に呼び出される ===========//  
        @Override  
        public void onDestroy() {
            super.onDestroy();
            mHandler.removeCallbacks(drawRunnable);
        }
  
        //====== 表示状態変更時に呼び出される ===========//  
        @Override  
        public void onVisibilityChanged(boolean visible) {
            this.visible = visible;  
  
            if (visible) {
                drawFrame();
            } else {
                mHandler.removeCallbacks(drawRunnable);
            }
        }  
  
        //////////////サーフェイス ////////////////////  
        //======生成時 ===========//  
        @Override  
        public void onSurfaceCreated(SurfaceHolder surfaceHolder) {
            super.onSurfaceCreated(surfaceHolder);
        }
  
        //======変更時 ===========//  
        @Override  
        public void onSurfaceChanged(SurfaceHolder holder, int format, int width , int height) {
            super.onSurfaceChanged(holder, format, width, height);

            this.width = width;
            this.height = height;  

            drawFrame();
        }
  
        //======破棄時 ===========//  
        @Override  
        public void onSurfaceDestroyed(SurfaceHolder holder) {  
            super.onSurfaceCreated(holder);

            visible = false;

            mHandler.removeCallbacks(drawRunnable);
        }
  
        //////////////////////////////////////////////////  
  
        //======オフセット変更時 ===========//  
        @Override  
        public void onOffsetsChanged(float xOffset, float yOffset, float xStep, float yStep, int xPixels, int yPixels) {  
            drawFrame();
        }
  
        //======描画 ===========//  
        private void drawFrame() {  
  
            final SurfaceHolder holder = getSurfaceHolder();  
  
            Canvas canvas = null;  
  
            try {  
  
                // キャンバスをロック  
                canvas = holder.lockCanvas();  
  
                /************************  
                 * 描画処理  
                 *************************/  
                if (canvas != null) {
                    canvas.drawColor(Color.WHITE);        // 背景色
                    canvas.drawBitmap(image, x, y, null); // 画像の表示
                }
  
                //---壁のあたり判定-------------  
  
                // 壁に当たる度に画像をランダムで切り替える  
                if (x < 0 || width - image.getWidth() < x) {
                    speedX = -speedX;
                    image = BitmapFactory.decodeResource(getResources(), imgPath[rand.nextInt(4)]);
                }
  
                if (y < 0 || height - image.getHeight() < y) {
                    speedY = -speedY;
                    image = BitmapFactory.decodeResource(getResources(), imgPath[rand.nextInt(4)]);
                }  
  
                x += speedX;
                y += speedY;
  
            } finally {
                // Canvas アンロック
                if (canvas != null) {
                    holder.unlockCanvasAndPost(canvas);
                }
            }

            // 次の描画をセット
            mHandler.removeCallbacks(drawRunnable);  

            if (visible) {
                mHandler.postDelayed(drawRunnable, 60);
            }
        }

        //======タッチイベント ===========//  
        @Override  
        public void onTouchEvent(MotionEvent event) {  
            // 画面をタッチすると画像がランダムで切り替わる
            switch(event.getAction()) {
            case MotionEvent.ACTION_UP:
                image = BitmapFactory.decodeResource(getResources(), imgPath[rand.nextInt(4)]);
                break;
            }
        }
    }
}

今回、ライブ壁紙を作ってみて結構面白いなと感じたのでもっといろいろ試してみたいと思いました!