2014年6月2日 星期一

幫人創作Live Wallpaper 約$100至$500

Live Wallpaper 是用 android programming 製作並非拍攝video咁簡單。Live Wallpaper 比較節省電力 互動性高 正統的方法。

如果你想表白定情,推銷享受, 炫耀, 娛樂或發揮創意,可以將你的idea或者要求email至 trrzoom@yahoo.com.hk價錢取決於要求的難度一般約$100$500

整個project包含四個step:

Step 1: 發送你的要求:
你可以參考以下四點:
1)      形容你的要求
2)      整個Live Wallpaper的草圖
3)      附加圖片
4)      附加參考的Live Wallpaper

Step 2: 討論你的要求
我會問清楚你的要求, 分析清楚你的要求, 講清楚我個計劃, 並給予你一個價錢

Step 3: 製作
製作時, 你可以放心休息, 一般需要3, 製造完成後將會通知你

Step 4: 交收
交收前會拍片比你, 如果沒有問題, 當面交收apk, 你只需自備手指或電話, 交收後版權歸你; 如果有問題, 可以告知我, 並改善製作

暫時只限android, 小弟部Mac機壞左 )…(

創作例子:
如仍有疑問,可email至 trrzoom@yahoo.com.hk

2014年5月29日 星期四

After break the source code of Floppy Bird

After two hours to make the elementary program of the game Floppy Bird, I decided to modify the original one. To implement that, I have added a classical background "The Sharp And  The Ship". Also, I used "Brushing Bird" to replace "Upward Bird" and "Downward Bird". Of course, there were also many raw duties such as ranking. Finally, I uploaded it and named it as "Brushing Bird". I hope that you will enjoy that.

2014年5月27日 星期二

Breaking the source code (Floppy Bird) (Part III)


The previous parts show that it is extremely easy to make the Floppy Bird. Right, it has many places which this game should improve. Yet, my opinion is that simple games have some irreplaceable advantages. This article would display my idea, which also shows one of the irreplaceable advantage.

My idea is to make it as a live wall paper!

Suppose that you follow the step in Part I and Part II. You now just need to spend 5 minutes to implement that idea. Why it is still easy? This is because you use Canvas to draw everything in the MainActivity in Part I and Part II while the engine of live wall paper uses the technique of Canvas too. In other words, you just need to copy the code from the previous part and paste it in the engine of live wall paper. Of course, a few code should be modified. Overall, there is two classes in this project.

Step 1:
Copy pillar.java to this live wall paper project. The first class is done easily!

Step 2:
Make the engine for this live wall paper. You may be confused how to make it without the knowledge of live wall paper. In my opinion, you just need to search this point in google and then copy the related code format. If you finish your first live wall paper, you will know the format to make your product for the next time.

Right, Floppy_Crack_In_LiveWallPaper.java below shows my whole codes in the engine. Apart from the highlighted codes, they are the essential codes for live wall paper. You could consider it as a format for writing a letter. For example, onSurfaceChanged is to delete the screen rotation, onVisibilityChanged is to detect whether the wall is enjoyed by the user and onTouchEvent is to detect touch event.

Step 3:
Copy the code in floppy_crack.java:
1) copy the variable
2) copy the code when initialization (onCreate)
3) copy the code for canvas to draw
4) copy the code for touch event

Step 4:
Ask service in xml.

Conclusion:
Since the game is simple, it is extremely easy for me to copy the original codes to the live wall paper engine. Thus, you just need to spend about 5 minutes to finish this parts. I hope that you could enjoy this technique and apply it on your product.

Floppy_Crack_In_LiveWallPaper.java:
public class Floppy_Crack_In_LiveWallPaper extends WallpaperService{
     private final Handler mHandler = new Handler();
     public static MyEngine globalEngine;
     @Override
     public Engine onCreateEngine()
     {
         globalEngine=new MyEngine();
         return globalEngine;
     }
     public class MyEngine extends Engine
     {
         private float x=0;
         private float y=0;
         private int speed;
        
         private Paint paint;
         private Bitmap bird_a_upward;
         private Bitmap bird_b_downward;
        
         private long previous;
        
         private pillar resistance[];
        
         private final Runnable myDraw= new Runnable()
         {
              public void run()
              {
                  draw();
              }
         };
         @Override
         public void onCreate(SurfaceHolder surfaceHolder)
         {
              setTouchEventsEnabled(true);
             
              y=200;
             
              paint=new Paint();
             
              speed=0;
             
              bird_a_upward=BitmapFactory.decodeResource(getResources(), R.drawable.upward_bird);
              bird_b_downward=BitmapFactory.decodeResource(getResources(), R.drawable.downward_bird);
             
              Date temp=new Date();
              previous=temp.getTime();
             
              resistance=new pillar[10];
              for(int i=0;i<10;i++)
              {
                  resistance[i]=new pillar((float)i*200+1000);
              }
             
              mHandler.removeCallbacks(myDraw);
              mHandler.post(myDraw);
             
              super.onCreate(surfaceHolder);
         }
        
         @Override
         public void onTouchEvent(MotionEvent b) {
              if(b.getAction()==MotionEvent.ACTION_DOWN)
              {
                  upward();
              }
              super.onTouchEvent(b);
         }

         @Override
         public void onVisibilityChanged(boolean visible)
         {
              System.gc();
              if(visible)
                  mHandler.post(myDraw);
              else
                  mHandler.removeCallbacks(myDraw);
         }
         @Override
         public void onSurfaceChanged(SurfaceHolder holder,int format,int width,int height)
         {
              System.gc();
              super.onSurfaceChanged(holder,format,width,height);
         }
         @Override
         public void onOffsetsChanged(float xOffset, float yOffset,
                  float xOffsetStep, float yOffsetStep, int xPixelOffset,
                  int yPixelOffset) {
             
              super.onOffsetsChanged(xOffset, yOffset, xOffsetStep, yOffsetStep,
                       xPixelOffset, yPixelOffset);
         }

         @Override
         public void onDestroy()
         {
              mHandler.removeCallbacks(myDraw);
              super.onDestroy();
         }
        
         public void upward()
         {
              speed=-20;
         }
        
         public void draw()
         {
              try
              {
                  final SurfaceHolder holder=getSurfaceHolder();
                  Canvas canvas=holder.lockCanvas();
                 
                  if(canvas!=null)
                  {
                       canvas.drawColor(Color.WHITE);
                      
                       Date temp=new Date();
                       long now=temp.getTime();
                      
                       if(now-previous>50)
                       {
                           previous=now;
                           if(y>canvas.getHeight()-bird_b_downward.getHeight()-100)
                           {
                                y-=5;
                                speed=-20;
                           }
                           else
                                if(y<0)
                                {
                                     y+=5;
                                     speed=20;
                                }
                                else
                                     y+=speed;
                          
                           speed+=5;
                          
                           boolean move_or_not=true;
                           for(int i=0;i<10;i++)
                           {   
                                resistance[i].ran_the_gap(canvas.getHeight());
                                if(!resistance[i].detection(x, y, bird_b_downward.getWidth(),bird_b_downward.getHeight()))
                                {
                                     move_or_not=false;
                                     break;
                                }
                           }
                           if(move_or_not)
                                for(int i=0;i<10;i++)
                                     resistance[i].move();
                       }
                       if(speed>0)
                       {
                           canvas.drawBitmap(bird_b_downward, x, y, paint);
                       }
                       else
                       {
                           canvas.drawBitmap(bird_a_upward, x, y, paint);
                       }
                       for(int i=0;i<10;i++)
                       {
                           resistance[i].show_pillar(canvas);
                       }
                       holder.unlockCanvasAndPost(canvas);
                       mHandler.post(myDraw);
                  }
              }
              catch(Exception except)
              {
                  mHandler.post(myDraw);
              }
         }
     }
}

pillar.java:
public class pillar {
     private final float width_of_pillar=50;
     private final float gap_for_life=200;
    
     private float position_y;
     private float position_x;
    
     private Paint paint;
    
     public pillar(float starting_x)
     {
         this.position_x=starting_x;
         this.position_y=100;
        
         paint=new Paint();
         paint.setColor(Color.BLACK);
     }
    
     public void ran_the_gap(float screen_height)
     {
         if(position_x==800)
              this.position_y=(float) (Math.random()*(screen_height-gap_for_life));
     }
    
     public void show_pillar(Canvas canvas_reference)
     {
         canvas_reference.drawRect(position_x, 0, position_x+width_of_pillar, position_y, paint);
         canvas_reference.drawRect(position_x, position_y+gap_for_life, position_x+width_of_pillar, canvas_reference.getHeight(), paint);
     }
    
     public void move()
     {
         position_x-=5;
         if(position_x==-100)
              position_x+=2000;
     }
    
     public boolean detection(float location_bird_x,float location_bird_y,float width_bird,float height_bird)
     {
         if(position_x>location_bird_x-width_of_pillar
                  &&position_x<location_bird_x+width_bird)
         {
              if(location_bird_y>position_y&&location_bird_y+height_bird<position_y+gap_for_life)
                  return true;
              else
                  return false;
         }
         return true;
     }

}

livewallpaper.xml: (additional file in xml) (You should change it to your data since it is metadata of your live wall paper)
<?xml version="1.0" encoding="utf-8"?>
<wallpaper xmlns:android="http://schemas.android.com/apk/res/android"
    android:author="@string/author"
    android:description="@string/describe"
    android:thumbnail="@drawable/iconful"/>

additional code in AndroidManifest.xml
<uses-feature android:name="android.software.live_wallpaper" />

additional code in AndroidManifest.xml
<service
            android:name="com.wallpaper.wave.waving"
            android:configChanges="keyboardHidden|orientation"
            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/livewallpaper" />
        </service>