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>

沒有留言:

張貼留言