Cách làm Livewallpaper - With Andengine

Thảo luận trong 'Điện thoại, viễn thông' bắt đầu bởi tuann, 2/9/12.

  1. tuann Guest

    tuann

    Mình mới nghiên cứu và làm xong 1 cái livewallpaper cũng hoàn chỉnh. Nó giông screensaver trên windows 7, Bubbles.
    Chia sẽ cùng các bạn hen.

    1. Tạo project android Bubbles có activity là BubblesActivity, add các gói andengine.jar, andenginelivewallpaper.jar, andenginephysicbox2dextension.jar
    (trong file mình gửi sẽ có các gói này)

    2. Tạo 1 class Settings.java,

    3. Trong thư mục res/xml, tạo 2 file wallpaper.xml và wallpaper_settings.xml
    wallpaper.xml: sẽ include activity của class Settings
    PHP:
    <?xml version="1.0" encoding="UTF-8"?>
    <wallpaper
            xmlns:android="http://schemas.android.com/apk/res/android"  
            android:thumbnail="@drawable/icon"
            android:settingsActivity="com.live.Settings"/>
    wallpaper_settings.xml chứa 1 checkbox, nếu background dc check sẽ hiện ra, ko check sẽ ko hiện background.
    PHP:
    <?xml version="1.0" encoding="utf-8"?>

    <PreferenceScreen
            xmlns:android="http://schemas.android.com/apk/res/android"
            android:title="Settings"
            >
            <CheckBoxPreference android:key="pref_background" android:defaultValue="true" android:title="Background">
            </CheckBoxPreference>
            
    </PreferenceScreen>
    4. Edit file manifest.xml, sử dụng <uses-feature android:name="android.software.live_wallpaper" />, và khai báo các service livewallpaper và activity Setting
    PHP:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.live"
          android:versionCode="1"
          android:versionName="1.0">
        
        <uses-sdk android:minSdkVersion="7" />
        
        <uses-feature android:name="android.software.live_wallpaper" />

        <application android:icon="@drawable/icon" android:label="@string/app_name">
            <service
                android:name=".BubblesActivity"
                android:enabled="true"
                android:icon="@drawable/icon"
                android:label="@string/app_name"
                android:permission="android.permission.BIND_WALLPAPER">
                <intent-filter>
                    <action android:name="android.service.wallpaper.WallpaperService" />
                </intent-filter>
                <meta-data
                    android:name="android.service.wallpaper" 
                    android:resource="@xml/wallpaper" />
            </service>
           
           <activity
                android:label="@string/wallpaper_settings"
                android:name=".Settings"
                android:theme="@android:style/Theme.Light.WallpaperSettings"
                android:exported="true">
            </activity>

        </application>
    </manifest>
    5. Tạo class Ball.java , kế thừa lớp Sprite, cài đặt thông số fixtureDef là trọng lượng, độ đàn hồi và ma sát
    Ở hàm onManageUpdate , sẽ luôn cho nó hiển thị ở 1 vị trí cố định, tại vì khi va chạm thì nó sẽ xoay theo hướng va chạm, nhìn ko thật tế, nên mình gọi mBody.setTransform(mBody.getPosition().x, mBody.getPosition().y, 0); với 0 là giá trị góc xoay.
    PHP:
    package com.live;

    import org.anddev.andengine.entity.sprite.Sprite;
    import org.anddev.andengine.extension.physics.box2d.PhysicsConnector;
    import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
    import org.anddev.andengine.opengl.texture.region.TextureRegion;

    import com.badlogic.gdx.physics.box2d.Body;
    import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
    import com.badlogic.gdx.physics.box2d.FixtureDef;

    public class 
    Ball extends Sprite {
        
        public 
    Body mBody;
        
        public 
    Ball(float pXfloat pYfloat pTileWidthfloat pTileHeight,
                
    TextureRegion pTextureRegion) {
            
    super(pXpYpTileWidthpTileHeightpTextureRegion);
            
    setPhysicsWorld();
        }
        
        public 
    void setPhysicsWorld() {
            
    FixtureDef fixtureDef PhysicsFactory.createFixtureDef(0.005f1.005f0.085f);;
            
    mBody PhysicsFactory.createCircleBody(BubblesActivity.mfswthisBodyType.DynamicBodyfixtureDef);
            
    BubblesActivity.mfsw.registerPhysicsConnector(new PhysicsConnector(thismBody));
        }

        @
    Override
        
    public void onManagedUpdate(final float pSecondsElapsed) {
            
    super.onManagedUpdate(pSecondsElapsed);
            
    mBody.setTransform(mBody.getPosition().xmBody.getPosition().y0);
        }
    }
    6. File BublesActivity.java, có 8 trái bóng
    Hàm onLoadScene, chắc cũng quen thuộc với các bạn rồi, trong đây mình khai báo thêm các cái shape để làm viền, ko cho trái bóng ra khỏi
    Hàm getWind, dùng để tạo 1 cơn gió thổi (sau 1 khoản thời gian nhất định) làm các trái bóng bay lên, tránh trường hợp trái bóng đứng yên
    Hàm onConfigurationChanged dùng để xử lý khi xoay màn hình ngang
    PHP:
    package com.live;

    import java.util.ArrayList;

    import org.anddev.andengine.engine.camera.Camera;
    import org.anddev.andengine.engine.handler.IUpdateHandler;
    import org.anddev.andengine.engine.options.EngineOptions;
    import org.anddev.andengine.engine.options.EngineOptions.ScreenOrientation;
    import org.anddev.andengine.engine.options.resolutionpolicy.FillResolutionPolicy;
    import org.anddev.andengine.entity.primitive.Rectangle;
    import org.anddev.andengine.entity.scene.Scene;
    import org.anddev.andengine.entity.scene.background.ColorBackground;
    import org.anddev.andengine.entity.scene.background.SpriteBackground;
    import org.anddev.andengine.entity.shape.Shape;
    import org.anddev.andengine.entity.sprite.Sprite;
    import org.anddev.andengine.extension.physics.box2d.FixedStepPhysicsWorld;
    import org.anddev.andengine.extension.physics.box2d.PhysicsFactory;
    import org.anddev.andengine.extension.physics.box2d.util.Vector2Pool;
    import org.anddev.andengine.extension.ui.livewallpaper.BaseLiveWallpaperService;
    import org.anddev.andengine.opengl.texture.TextureOptions;
    import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlas;
    import org.anddev.andengine.opengl.texture.atlas.bitmap.BitmapTextureAtlasTextureRegionFactory;
    import org.anddev.andengine.opengl.texture.region.TextureRegion;
    import org.anddev.andengine.sensor.accelerometer.AccelerometerData;
    import org.anddev.andengine.sensor.accelerometer.IAccelerometerListener;
    import org.anddev.andengine.util.MathUtils;

    import android.content.res.Configuration;

    import com.badlogic.gdx.math.Vector2;
    import com.badlogic.gdx.physics.box2d.BodyDef.BodyType;
    import com.badlogic.gdx.physics.box2d.FixtureDef;

    public class 
    BubblesActivity extends BaseLiveWallpaperService implements IAccelerometerListener {
        
    // ===========================================================
        // Constants
        // ===========================================================
        
        
    public static final String SHARED_PREFS_NAME "livewallpapertemplatesettings";

        private static 
    int CAMERA_WIDTH 480;
        private static 
    int CAMERA_HEIGHT 800;
        
        private 
    float GRAVITY 0.78f;
        
        private 
    ScreenOrientation mInitOrientation ScreenOrientation.PORTRAIT;
        
        public static 
    FixedStepPhysicsWorld mfsw;
        public static 
    Scene scene;
        
        private 
    Vector2 wind = new Vector2(1,-10);

        
    // ===========================================================
        // Fields
        // ===========================================================
        
    public static BitmapTextureAtlas tt_ball;
        public static 
    TextureRegion tr_ball;
        
        public static 
    BitmapTextureAtlas tt_bar;
        public static 
    TextureRegion tr_bar;
        
        private 
    BitmapTextureAtlas tt_bg;
        private 
    TextureRegion tr_bg;
        private static 
    SpriteBackground mBackground;
        
        
    //Shared Preferences
        //private SharedPreferences mSharedPreferences;
        
        
    private final int MAX_BALL 8;
        private final 
    int BALL_SIZE=140;
        
        private 
    ArrayList<BallarrBall = new ArrayList<Ball>();
        private 
    int count 0;

        @
    Override
        
    public org.anddev.andengine.engine.Engine onLoadEngine()
        {
            
    Camera mCamera = new Camera(00CAMERA_WIDTHCAMERA_HEIGHT);
            
    EngineOptions eo = new EngineOptions(truemInitOrientation, new FillResolutionPolicy(), mCamera);
            
    eo.getTouchOptions().setRunOnUpdateThread(true);
            
    eo.getRenderOptions().disableExtensionVertexBufferObjects();
            return new 
    org.anddev.andengine.engine.Engine(eo);
        }

        @
    Override
        
    public void onLoadResources()
        {
            
    tt_ball = new BitmapTextureAtlas(256256TextureOptions.BILINEAR_PREMULTIPLYALPHA);
            
    tr_ball BitmapTextureAtlasTextureRegionFactory.createFromAsset(tt_ballthis"gfx/bubble.png"00);

            
    tt_bg = new BitmapTextureAtlas(10241024TextureOptions.BILINEAR_PREMULTIPLYALPHA);
            
    tr_bg BitmapTextureAtlasTextureRegionFactory.createFromAsset(tt_bgthis"gfx/bg.jpg"00);
            
            
    this.getEngine().getTextureManager().loadTexture(tt_ball);
            
    this.getEngine().getTextureManager().loadTexture(tt_bg);
        }

        @
    Override
        
    public Scene onLoadScene()
        {
            
    scene = new Scene();
            
            
    mBackground = new SpriteBackground(new Sprite(00,CAMERA_WIDTH,CAMERA_HEIGHTtr_bg));
            
    scene.setBackground(mBackground);
            
            
    // fixed step physic world
            
    mfsw = new FixedStepPhysicsWorld(30, new Vector2(0,GRAVITY), false);

            final 
    Shape ground = new Rectangle(0CAMERA_HEIGHT 2CAMERA_WIDTH2);
            final 
    Shape roof = new Rectangle(0, -30CAMERA_WIDTH2);
            final 
    Shape left = new Rectangle(-3002CAMERA_HEIGHT);
            final 
    Shape right = new Rectangle(CAMERA_WIDTH 3002CAMERA_HEIGHT);
            
            final 
    FixtureDef wallFixtureDef PhysicsFactory.createFixtureDef(0.005f0.9f0.1f);
            
    PhysicsFactory.createBoxBody(mfswgroundBodyType.StaticBodywallFixtureDef);
            
    PhysicsFactory.createBoxBody(mfswroofBodyType.StaticBodywallFixtureDef);
            
    PhysicsFactory.createBoxBody(mfswleftBodyType.StaticBodywallFixtureDef);
            
    PhysicsFactory.createBoxBody(mfswrightBodyType.StaticBodywallFixtureDef);

            
    scene.attachChild(ground);
            
    scene.attachChild(roof);
            
    scene.attachChild(left);
            
    scene.attachChild(right);
            
            for (
    int i=0MAX_BALLi++) {
                
    int x MathUtils.random(0CAMERA_WIDTH-BALL_SIZE);
                
    int y BALL_SIZE;
                final 
    Ball ball = new Ball(xyBALL_SIZEBALL_SIZEtr_ball);
                
    arrBall.add(ball);
                
    scene.attachChild(ball);
            }
            
            
    scene.registerUpdateHandler(mfsw);
            
            
    scene.registerUpdateHandler(getWind());
            return 
    scene;
        }
        
        public static 
    void displayBackground(boolean b) {
            if (
    b) {
                
    scene.setBackground(mBackground);
            } else {
                
    scene.setBackground(new ColorBackground(000));
            }
        }
        
        @
    Override
        
    public void onLoadComplete()
        {

        }
        
        @
    Override
        
    protected void onTap(final int pX, final int pY)
        {
            
        }
        

        @
    Override
        
    public void onPauseGame() {
            
        }

        @
    Override
        
    public void onResumeGame() {
            
        }

        @
    Override
        
    public void onAccelerometerChanged(AccelerometerData pAccelerometerData) {
            final 
    Vector2 gravity Vector2Pool.obtain(pAccelerometerData.getX(), GRAVITY);
            
    mfsw.setGravity(gravity);
            
    //Vector2Pool.recycle(gravity);
        
    }

        @
    Override
        
    public void onConfigurationChanged (Configuration newConfig){
            
    super.onConfigurationChanged(newConfig);
            if (
    mInitOrientation == ScreenOrientation.PORTRAIT) {
                if (
    newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    
    scene.setScaleX((float)CAMERA_WIDTH / (float)CAMERA_HEIGHT);
                    
    scene.setScaleY((float)CAMERA_HEIGHT / (float)CAMERA_WIDTH);
                }
                if (
    newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                    
    scene.setScale(1);
                }
            }
            if (
    mInitOrientation == ScreenOrientation.LANDSCAPE) {
                if (
    newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
                    
    scene.setScale(1);
                }
                if (
    newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    
    scene.setScaleX((float)CAMERA_WIDTH / (float)CAMERA_HEIGHT);
                    
    scene.setScaleY((float)CAMERA_HEIGHT / (float)CAMERA_WIDTH);
                }
            }
            
    // updateBackground();
            // update bottom & right;
        
    }
        
        private 
    IUpdateHandler getWind() {
            return new 
    IUpdateHandler() {

                @
    Override
                
    public void onUpdate(float pSecondsElapsed) {
                    
    count count 1;
                    if (
    count 400) {
                        for (
    Ball b arrBall) {
                            
    b.mBody.applyForce(windb.mBody.getWorldCenter());
                        }
                        
    count 0;
                    }
                }

                @
    Override
                
    public void reset() {
                    
                }
                
            };
        }
    }
    7. File Settings.java
    Hàm onSharedPreferenceChanged sẽ đc gọi khi user thay đổi settings.
    PHP:
    package com.live;


    import android.content.SharedPreferences;
    import android.os.Bundle;
    import android.preference.PreferenceActivity;

    public class 
    Settings extends PreferenceActivity implements SharedPreferences.OnSharedPreferenceChangeListener
    {    
        @
    Override
        
    protected void onCreate(Bundle icicle)
        {
            
    super.onCreate(icicle);
            
    getPreferenceManager().setSharedPreferencesName(BubblesActivity.SHARED_PREFS_NAME);
            
    addPreferencesFromResource(R.xml.wallpaper_settings);
            
    getPreferenceManager().getSharedPreferences().registerOnSharedPreferenceChangeListener(this);
        }

        @
    Override
        
    protected void onResume()
        {
            
    super.onResume();
        }

        @
    Override
        
    protected void onDestroy()
        {
            
    getPreferenceManager().getSharedPreferences().unregisterOnSharedPreferenceChangeListener(this);
            
    super.onDestroy();
        }

        @
    Override
        
    public void onSharedPreferenceChanged(SharedPreferences sharedPreferencesString key)
        {
            
    boolean isBG sharedPreferences.getBoolean("pref_background"true);
            
    BubblesActivity.displayBackground(isBG);
        }
    }

    8. Run và chạy, kết quả như hình đính kèm. Hi vọng giúp ích được cho mọi người.
    DOWNLOAD SOURCE
    DOWNLOAD FILE APK

    Thumbnails được đính kèm AndEngine - Cách làm Livewallpaper-livewallpaper.jpg

    Tg: tkMinh nguồn: cunghocandroid
     
    2 people like this.
    Đang tải...
  2. akavipno1 New Member

    akavipno1

    Tham gia ngày:
    8/7/13
    Bài viết:
    5
    Đã được thích:
    0
    Điểm thành tích:
    0
    Giới tính:
    Nam
    làm thế nào để vuốt màn hình sang trái hoặc phải thì thay đổi ảnh background của ứng dụng này vậy các bạn
     
  3. akavipno1 New Member

    akavipno1

    Tham gia ngày:
    8/7/13
    Bài viết:
    5
    Đã được thích:
    0
    Điểm thành tích:
    0
    Giới tính:
    Nam
    không ai giúp mình vụ này à @_@
     
  4. homatenbeo New Member

    homatenbeo

    Tham gia ngày:
    10/7/13
    Bài viết:
    2
    Đã được thích:
    0
    Điểm thành tích:
    0
    Giới tính:
    Nam
    bạn tìm hiểu về onOffsetsChanged nhé
     

Chia sẻ trang này