Slep 1 : Create class Aquarium
public class Aquarium { private AquariumThread _aquariumThread; private SurfaceHolder _surfaceHolder; private ArrayList<Renderable> _fishes; public Bitmap _backgroundImage; private Context _context; public void render(){ Canvas canvas = null; try{ canvas = this._surfaceHolder.lockCanvas(null); synchronized (this._surfaceHolder) { this.onDraw(canvas); } }finally{ if(canvas != null){ this._surfaceHolder.unlockCanvasAndPost(canvas); } } } protected void onDraw(Canvas canvas) { this.renderBackGround(canvas); for (Renderable renderable : this._fishes) { renderable.render(canvas); } }; public void start(){ this._aquariumThread.switchOn(); } public void stop(){ boolean retry = true; this._aquariumThread.switchOff(); while (retry) { try { this._aquariumThread.join(); retry = false; } catch (InterruptedException e) { // we will try it again and again... } } } public int getLeft() { return 0; } public int getRight() { return this._backgroundImage.getWidth(); } public void initialize(Context context, SurfaceHolder surfaceHolder) { this._aquariumThread = new AquariumThread(this); this._surfaceHolder = surfaceHolder; this._fishes = new ArrayList<Renderable>(); this._context = context; BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true; this._backgroundImage = BitmapFactory.decodeResource(context.getResources(), R.drawable.aquarium, options); this.addFishes(); } private void addFishes() { Point startPoint = new Point(50, 700); this._fishes.add(new ClownFish(this._context, this, startPoint, 90)); Point startPoint1 = new Point(150, 500); this._fishes.add(new ClownFish(this._context, this, startPoint1, 70)); Point startPoint2 = new Point(250, 300); this._fishes.add(new ClownFish(this._context, this, startPoint2, 50)); // moi them Point startPoint3 = new Point(350, 250); this._fishes.add(new ClownFish(this._context, this, startPoint3, 40)); Point startPoint4 = new Point(450, 200); this._fishes.add(new ClownFish(this._context, this, startPoint4, 15)); } private void renderBackGround(Canvas canvas) { canvas.drawBitmap(this._backgroundImage, 0, 0, null); } }
Step 2: Create class AquariumThread extends Thread
public class AquariumThread extends Thread { private Aquarium _aquarium; private boolean _running; public AquariumThread(Aquarium aquarium) { this._aquarium = aquarium; } public void switchOn(){ this._running = true; this.start(); } public void pause(){ this._running = false; synchronized(this){ this.notify(); } } public void switchOff(){ this._running = false; synchronized(this){ this.notify(); } } @Override public void run() { while(this._running){ this._aquarium.render(); } } }
Step 3: Create Interface Renderable
public interface Renderable { void render(Canvas canvas); }
Step 4: Create class FishSprite
public class FishSprite { /** * Private fields */ private Bitmap _currentSpriteBitmap; private Rect _drawRect; private int _fps; private int _noOfFrames; private int _currentFrame; private long _timer; private int _spriteWidth; private int _spriteHeight; private Point _position; public FishSprite(Bitmap spriteBitmap, int fps, int frameCount, Point startPoint) { this.initialize(); this._position = startPoint; this._currentSpriteBitmap = spriteBitmap; this._spriteHeight = spriteBitmap.getHeight(); this._spriteWidth = spriteBitmap.getWidth() / frameCount; this._drawRect = new Rect(0,0, this._spriteWidth, this._spriteHeight); this._fps = 1000 / fps; this._noOfFrames = frameCount; } private void initialize() { this._drawRect = new Rect(0,0,0,0); this._timer = 0; this._currentFrame = 0; } private void Update(long currentTime) { if(currentTime > this._timer + this._fps ) { this._timer = currentTime; this._currentFrame +=1; if(this._currentFrame >= this._noOfFrames) { this._currentFrame = 0; } } this._drawRect.left = this._currentFrame * this._spriteWidth; this._drawRect.right = this._drawRect.left + this._spriteWidth; } public void render(Canvas canvas, long currentTime) { this.Update(currentTime); Rect dest = new Rect(getXPos(), getYPos(), getXPos() + this._spriteWidth, getYPos() + this._spriteHeight); canvas.drawBitmap(this._currentSpriteBitmap, this._drawRect, dest, null); } public Point getPosition() { return _position; } public void setPosition(Point position) { this._position = position; } public int getYPos() { return this._position.y; } public int getXPos() { return this._position.x; } public void setYPos(int y) { this._position.y = y; } public void setXPos(int x) { this._position.x = x; } public int getWidth(){ return this._spriteWidth; } public int getHeight(){ return this._spriteHeight; } }Stempt 5: Create a class AquaticAnimal
public abstract class AquaticAnimal implements Renderable { private static int MAX_SPEED = 100; private Context _context; private Aquarium _aquarium; private FishSprite _leftSprite; private FishSprite _rightSprite; private int _direction = -1; private int _speedFraction; private long _previousTime; public AquaticAnimal(Context context, Aquarium aquarium){ this._context = context; this._aquarium = aquarium; } protected void initialize(Bitmap leftBitmap, Bitmap rightBitmap, int fps, int totalFrames, Point startPoint, int speed){ this._leftSprite = new FishSprite(leftBitmap, fps, totalFrames, startPoint); this._rightSprite = new FishSprite(rightBitmap, fps, totalFrames, startPoint); this._speedFraction = (MAX_SPEED / speed) * 10; } private FishSprite getSprite(){ if(this._direction < 0){ return this._leftSprite; } return this._rightSprite; } public int getDirection(){ FishSprite sprite = this.getSprite(); int xPos = sprite.getXPos(); if(this._direction < 0){ xPos += sprite.getWidth(); } if(xPos < this._aquarium.getLeft()){ this._direction = 1; }else if(xPos > this._aquarium.getRight()){ this._direction = -1; }else{ // Do nothing } return this._direction; } public Context getContext(){ return this._context; } public Aquarium getAquarium(){ return this._aquarium; } @Override public void render(Canvas canvas){ long currentTime = System.currentTimeMillis(); this.getSprite().render(canvas, currentTime); this.swim(currentTime); } public void swim(long currentTime){ long diff = currentTime - this._previousTime; if(diff > this._speedFraction){ int currentX = this.getSprite().getXPos(); this.getSprite().setXPos(currentX + this.getDirection()); this._previousTime = currentTime; } } }Stemp 6: Create a class ClownFish
public class ClownFish extends AquaticAnimal { private static final int TOTAL_FRAMES_IN_SPRITE = 20; private static final int CLOWN_FISH_FPS = 20; public ClownFish(Context context, Aquarium aquarium, Point startPoint, int speed){ super(context, aquarium); BitmapFactory.Options options = new BitmapFactory.Options(); options.inPurgeable = true; Bitmap leftBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.left, options); BitmapFactory.Options options1 = new BitmapFactory.Options(); options1.inPurgeable = true; Bitmap rightBitmap = BitmapFactory.decodeResource(getContext().getResources(), R.drawable.right , options1); this.initialize(leftBitmap, rightBitmap, CLOWN_FISH_FPS, TOTAL_FRAMES_IN_SPRITE, startPoint, speed); } public void render(Canvas canvas){ super.render(canvas); } }Stemp 7: Create service by a class AquariumWallpaperService
public class AquariumWallpaperService extends WallpaperService { @Override public Engine onCreateEngine() { return new AquariumWallpaperEngine(); } class AquariumWallpaperEngine extends Engine{ private Aquarium _aquarium; public AquariumWallpaperEngine() { this._aquarium = new Aquarium(); this._aquarium.initialize(getBaseContext(), getSurfaceHolder()); } @Override public void onVisibilityChanged(boolean visible) { if(visible){ this._aquarium.render(); } } @Override public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height) { super.onSurfaceChanged(holder, format, width, height); } @Override public void onSurfaceCreated(SurfaceHolder holder) { super.onSurfaceCreated(holder); this._aquarium.start(); } @Override public void onSurfaceDestroyed(SurfaceHolder holder) { super.onSurfaceDestroyed(holder); this._aquarium.stop(); } @Override public void onTouchEvent(MotionEvent event) { super.onTouchEvent(event); float x = event.getX(); float y = event.getY(); Log.d("anhtt","x = " +x +" yy == " +y); } } }Stemp 8: Setting file Manifest.xml
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <service android:name=".demo.AquariumWallpaperService" android:enabled="true" android:label="Wallpaper Example" android:permission="android.permission.BIND_WALLPAPER"> <intent-filter> <action android:name="android.service.wallpaper.WallpaperService"> </action> </intent-filter> <meta-data android:name="android.service.wallpaper" android:resource="@xml/mywallpaper"> </meta-data> </service> <activity android:name=".wallpaper.MyPreferencesActivity" android:exported="true" android:label="@string/app_name" android:theme="@android:style/Theme.Light.WallpaperSettings"> </activity> <activity android:name=".MainActivity" android:label="@string/app_name" android:theme="@android:style/Theme.Light.WallpaperSettings"> <intent-filter> <action android:name="android.intent.action.MAIN"/> <category android:name="android.intent.category.LAUNCHER"/> </intent-filter> </activity> </application> <uses-feature android:name="android.software.live_wallpaper" android:required="true"> </uses-feature>Step 9: Create file xml by Wallpaper.xml and presf.xml
<?xml version="1.0" encoding="utf-8"?><wallpaper xmlns:android="http://schemas.android.com/apk/res/android" android:description="@string/app_name" android:settingsActivity="com.anhttvn.fishlivewallpaper.wallpaper.MyPreferencesActivity" android:thumbnail="@mipmap/ic_launcher"/>
Image Aquarium, fish left and fish right you can download below
No comments:
Post a Comment