Hatena::ブログ(Diary)

麗ちゃんとママの実験ノート

2010-03-24

[][] スライドパズルでViewとSurfaceViewとOpenGL(GLSurfaceView)を比較 00:52

臨月妊婦の暇つぶしに、スライドパズルを例に、ViewとSurfaceViewとGLSurfaceViewの比較をメモします。アプリの画面はこんな感じ。

f:id:chiakisugimoto:20100325010758p:image

#ちなみに写真は、産休に入る際、職場の皆さんから頂いたお花です。

今日はSurfaceViewのソースコードまで。お腹が苦しいので、解説はまた。

<SlidePuzzle.java>

package com.chiaki.example;

import android.app.Activity;
import android.os.Bundle;
import android.view.Window;

public class SlidePuzzle extends Activity {
  private boolean view_flg = false;
  private boolean surfaceview_flg = false;
  private boolean glsurfaceview_flg = true;
    private SlidePuzzle_View mSlidePuzzle_View;
    private SlidePuzzle_SurfaceView mSlidePuzzle_SurfaceView;
    private SlidePuzzle_GLSurfaceView mSlidePuzzle_GLSurfaceView;

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        if (surfaceview_flg){
            mSlidePuzzle_SurfaceView = new SlidePuzzle_SurfaceView(this);
            setContentView(mSlidePuzzle_SurfaceView);        	
        }else if (view_flg){
            mSlidePuzzle_View = new SlidePuzzle_View(this);
            setContentView(mSlidePuzzle_View);        	
        }else if (glsurfaceview_flg){
        	mSlidePuzzle_GLSurfaceView = new SlidePuzzle_GLSurfaceView(this);
        	setContentView(mSlidePuzzle_GLSurfaceView);        	
        }
    }
}

<SlidePuzzle_SurfaceView.java>

package com.chiaki.example;

import java.util.Random;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class SlidePuzzle_SurfaceView extends SurfaceView implements SurfaceHolder.Callback, Runnable {
    private Random rand=new Random();
    private Bitmap image;            
    private int[]  data=new int[25]; 
    private Thread mThread;
  private SurfaceHolder mSurfaceHolder;

    public SlidePuzzle_SurfaceView(Context context) {
	super(context);
        initialize(context);

        for (int i=0;i<25;i++) data[i]=i;
        loadPicture(context);

        setFocusable(true);      
        setFocusableInTouchMode(true); 
    }
	
    private void initialize(Context context) {
        mSurfaceHolder = getHolder();
        mSurfaceHolder.addCallback(this);
        mSurfaceHolder.setFixedSize(getWidth(), getHeight());
	setFocusable(true);

     }

    public void loadPicture(Context ctx) {
        Context context= ctx;
        Resources r=context.getResources();
        int resID=R.drawable.picture;
        image=BitmapFactory.decodeResource(r,resID); 
        image =  Bitmap.createScaledBitmap(image, 300, 300, true); 

        int[] DIR={
            KeyEvent.KEYCODE_DPAD_UP,
            KeyEvent.KEYCODE_DPAD_DOWN,
            KeyEvent.KEYCODE_DPAD_LEFT,
            KeyEvent.KEYCODE_DPAD_RIGHT
        };
        for (int i=99;i>=0;i--) {
            slidePiece(DIR[(rand.nextInt()>>>1)%4]);
        }        
    }

    private void slidePiece(int key) {
        int freeIdx=0;
        for (; freeIdx<25; freeIdx++) {
            if (data[freeIdx]==24) break;
        }
                
        if (key==KeyEvent.KEYCODE_DPAD_UP && freeIdx/5<4) {
            data[freeIdx]=data[freeIdx+5];
            data[freeIdx+5]=24;
        } else if (key==KeyEvent.KEYCODE_DPAD_DOWN && freeIdx/5>0) {
            data[freeIdx]=data[freeIdx-5];
            data[freeIdx-5]=24;
        } else if (key==KeyEvent.KEYCODE_DPAD_LEFT && freeIdx%5<4) {
            data[freeIdx]=data[freeIdx+1];
            data[freeIdx+1]=24;
        } else if (key==KeyEvent.KEYCODE_DPAD_RIGHT && freeIdx%5>0) {
            data[freeIdx]=data[freeIdx-1];
            data[freeIdx-1]=24;
        }
        
    }    

	@Override
	public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void surfaceCreated(SurfaceHolder arg0) {
	    mThread = new Thread(this);
	    mThread.start();
		
	}

	@Override
	public void surfaceDestroyed(SurfaceHolder arg0) {
		mThread = null;		
	}

	@Override
	public void run() {
	    Canvas canvas = null;
	    while (mThread != null) {
	      try {
	        canvas = mSurfaceHolder.lockCanvas();
	        drawPuzzle(canvas);
	      } finally {
	          if (canvas != null)
	        	  mSurfaceHolder.unlockCanvasAndPost(canvas);
	        }
	      }
	}		
	
	public void drawPuzzle(Canvas canvas) {
        if (image==null) return;

        boolean complete=true;
        for (int i=0;i<25;i++) {
            if (data[i]!=i) complete=false;
        }
        
        Paint paint=new Paint();
        paint.setAntiAlias(true);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.argb(255,0,0,0));
        canvas.drawRect(
            new Rect(0,0,getWidth(),getHeight()),paint);
        int bx=(getWidth()-300)/2;
        int by=(getHeight()-300)/2;

        for (int i=0;i<25;i++) {
            int sx=data[i]%5;
            int sy=data[i]/5;
            int dx=i%5;
            int dy=i/5;
            if (!complete) {
                paint.setColor(Color.argb(255,255,255,255));
                paint.setStyle(Paint.Style.STROKE);
            }
            if (data[i]!=24) {
            	if (getmode() == KeyEvent.KEYCODE_DPAD_UP){
            		if (i <= (5*gettouchY() + gettouchX()) && i > (5*getfreeY() + getfreeX()) && (i == (5*getfreeY() + getfreeX())+5 || i == (5*getfreeY() + getfreeX())+10 || i == (5*getfreeY() + getfreeX())+15 || i == (5*getfreeY() + getfreeX())+20) && getslide_ysum() <= 60 && getslide_ysum() >= 0){
                        canvas.drawRect(
                                new Rect(bx+60*dx,by+60*dy-getslide_ysum(),
                                    bx+60*dx+60,by+60*dy+60-getslide_ysum()),
                                paint);

                        canvas.drawBitmap(image,
                                new Rect(60*sx,60*sy,
                                    60*sx+60,60*sy+60),
                                new Rect(bx+60*dx,by+60*dy-getslide_ysum(),
                                    bx+60*dx+60,by+60*dy+60-getslide_ysum()),
                                null);            		                    	            				            			                				                						
            		}else{
                        canvas.drawRect(
                                new Rect(bx+60*dx,by+60*dy,
                                    bx+60*dx+60,by+60*dy+60),
                                paint);

                                canvas.drawBitmap(image,
                                        new Rect(60*sx,60*sy,
                                            60*sx+60,60*sy+60),
                                        new Rect(bx+60*dx,by+60*dy,
                                            bx+60*dx+60,by+60*dy+60),
                                        null);                			
            		}
                    if (getslide_ysum() >= 60){
       	    			for (int j=freeY;j<touchY;j++) {
       	    				slidePiece(KeyEvent.KEYCODE_DPAD_UP);
       	    			}
       			    	s_touchX = 0;
       			    	s_touchY = 0;
       			    	e_touchX = 0;
       			    	e_touchY = 0;
       			    	slide_x = 0;
       			    	slide_y = 0;
       			    	slide_xsum = 0;
       			    	slide_ysum = 0;
       			    	reach_flg = true;
                    }            		
            	}
        		if (getmode() == KeyEvent.KEYCODE_DPAD_DOWN){
            		if (i >= (5*gettouchY() + gettouchX()) && i < (5*getfreeY() + getfreeX()) && (i == (5*getfreeY() + getfreeX())-5 || i == (5*getfreeY() + getfreeX())-10 || i == (5*getfreeY() + getfreeX())-15 || i == (5*getfreeY() + getfreeX())-20) && getslide_ysum() > -60 && getslide_ysum() < 0){
                        canvas.drawRect(
                                new Rect(bx+60*dx,by+60*dy-getslide_ysum(),
                                    bx+60*dx+60,by+60*dy+60-getslide_ysum()),
                                paint);

                        canvas.drawBitmap(image,
                                new Rect(60*sx,60*sy,
                                    60*sx+60,60*sy+60),
                                new Rect(bx+60*dx,by+60*dy-getslide_ysum(),
                                    bx+60*dx+60,by+60*dy+60-getslide_ysum()),
                                null);            		                    	            				            			                				                					
            		}else{
                        canvas.drawRect(
                                new Rect(bx+60*dx,by+60*dy,
                                    bx+60*dx+60,by+60*dy+60),
                                paint);

                                canvas.drawBitmap(image,
                                        new Rect(60*sx,60*sy,
                                            60*sx+60,60*sy+60),
                                        new Rect(bx+60*dx,by+60*dy,
                                            bx+60*dx+60,by+60*dy+60),
                                        null);                			
            		}
                }                    
                if (getslide_ysum() <= -60){
   	    			for (int j=freeY;j>touchY;j--) {
   	    				slidePiece(KeyEvent.KEYCODE_DPAD_DOWN);
   	    			}
   			    	s_touchX = 0;
   			    	s_touchY = 0;
   			    	e_touchX = 0;
   			    	e_touchY = 0;
   			    	slide_x = 0;
   			    	slide_y = 0;
   			    	slide_xsum = 0;
   			    	slide_ysum = 0;
   			    	reach_flg = true;
                }
                
            	if (getmode() == KeyEvent.KEYCODE_DPAD_RIGHT){
            		if (i < (5*getfreeY() + getfreeX()) && i >= (5*gettouchY() + gettouchX()) && getslide_xsum() <= 60 && getslide_xsum() >= 0){
                        canvas.drawRect(
                                new Rect(bx+60*dx+getslide_xsum(),by+60*dy,
                                    bx+60*dx+60+getslide_xsum(),by+60*dy+60),
                                paint);

                        canvas.drawBitmap(image,
                                new Rect(60*sx,60*sy,
                                    60*sx+60,60*sy+60),
                                new Rect(bx+60*dx+getslide_xsum(),by+60*dy,
                                    bx+60*dx+60+getslide_xsum(),by+60*dy+60),
                                null);            		                    	            				            			                				                						
            		}else{
                        canvas.drawRect(
                                new Rect(bx+60*dx,by+60*dy,
                                    bx+60*dx+60,by+60*dy+60),
                                paint);

                         canvas.drawBitmap(image,
                                new Rect(60*sx,60*sy,
                                    60*sx+60,60*sy+60),
                                new Rect(bx+60*dx,by+60*dy,
                                    bx+60*dx+60,by+60*dy+60),
                                null);                			
            		}
                    if (getslide_xsum() >= 60){
       	    			for (int j=freeX;j>touchX;j--) {
       	    				slidePiece(KeyEvent.KEYCODE_DPAD_RIGHT);
       	    			}
       			    	s_touchX = 0;
       			    	s_touchY = 0;
       			    	e_touchX = 0;
       			    	e_touchY = 0;
       			    	slide_x = 0;
       			    	slide_y = 0;
       			    	slide_xsum = 0;
       			    	slide_ysum = 0;
       			    	reach_flg = true;
                    }
            	}

            	if (getmode() == KeyEvent.KEYCODE_DPAD_LEFT){
            		if (i > (5*getfreeY() + getfreeX()) && i <= (5*gettouchY() + gettouchX()) && getslide_xsum() >= -60 && getslide_xsum() <= 0){
                        canvas.drawRect(
                                new Rect(bx+60*dx+getslide_xsum(),by+60*dy,
                                    bx+60*dx+60+getslide_xsum(),by+60*dy+60),
                                paint);

                        canvas.drawBitmap(image,
                                new Rect(60*sx,60*sy,
                                    60*sx+60,60*sy+60),
                                new Rect(bx+60*dx+getslide_xsum(),by+60*dy,
                                    bx+60*dx+60+getslide_xsum(),by+60*dy+60),
                                null);            		                    	            				            			                				                						
            		}else{
                        canvas.drawRect(
                                new Rect(bx+60*dx,by+60*dy,
                                    bx+60*dx+60,by+60*dy+60),
                                paint);

                         canvas.drawBitmap(image,
                                new Rect(60*sx,60*sy,
                                    60*sx+60,60*sy+60),
                                new Rect(bx+60*dx,by+60*dy,
                                    bx+60*dx+60,by+60*dy+60),
                                null);                			
            		}
                    if (getslide_xsum() <= -60){
       	    			for (int j=freeX;j<touchX;j++) {
       	    				slidePiece(KeyEvent.KEYCODE_DPAD_LEFT);
       	    			}
       			    	s_touchX = 0;
       			    	s_touchY = 0;
       			    	e_touchX = 0;
       			    	e_touchY = 0;
       			    	slide_x = 0;
       			    	slide_y = 0;
       			    	slide_xsum = 0;
       			    	slide_ysum = 0;
       			    	reach_flg = true;
                    }
            	}

                if (getmode() == -1 || getslide_ysum() == -60 || getslide_ysum() == 60 || getslide_xsum() == -60 || getslide_xsum() == 60){
                    canvas.drawRect(
                            new Rect(bx+60*dx,by+60*dy,
                                bx+60*dx+60,by+60*dy+60),
                            paint);

                            canvas.drawBitmap(image,
                                    new Rect(60*sx,60*sy,
                                        60*sx+60,60*sy+60),
                                    new Rect(bx+60*dx,by+60*dy,
                                        bx+60*dx+60,by+60*dy+60),
                                    null);
                }
                
            }
        }
        if (complete) {
            paint.setTextSize(32);
            paint.setColor(Color.argb(255,255,0,0));
            String str="Congratulations!";
            int w=(int)paint.measureText(str);
            canvas.drawText(str,bx+(300-w)/2,by+270,paint);                
        }    	
	}
	
    @Override
    public boolean onTouchEvent(MotionEvent event) {

	    switch( event.getAction() ){
	   	     
   	    case MotionEvent.ACTION_DOWN :
   	    	s_touchX = 0;
   	    	s_touchY = 0;
   	    	e_touchX = 0;
   	    	e_touchY = 0;

   	    	s_touchX = (int) event.getX();
   	    	s_touchY = (int) event.getY();

   	    	touchX=(int)(event.getX()-(getWidth()-300)/2)/60;
   	    	touchY=(int)(event.getY()-(getHeight()-300)/2)/60;
   	    	if (touchX<0 || 5<=touchX) return true;
   	    	if (touchY<0 || 5<=touchY) return true;
            
   	    	freeX=0;
   	    	freeY=0;
   	    	for (int i=0;i<25;i++) {
   	    		if (data[i]==24) {
   	    			freeX=i%5;
   	    			freeY=i/5;
   	    			break;
   	    		}
   	    	}
            
   	    	if (touchX==freeX) {
   	    		if (freeY<touchY) {
   	    			mode = KeyEvent.KEYCODE_DPAD_UP;
   	    		} else if (freeY>touchY) {
   	    			mode = KeyEvent.KEYCODE_DPAD_DOWN;
   	    		}
   	    	} else if (touchY==freeY) {
   	    		if (freeX<touchX) {
   	    			mode = KeyEvent.KEYCODE_DPAD_LEFT;
   	    		} else if (freeX>touchX) {
   	    			mode = KeyEvent.KEYCODE_DPAD_RIGHT;
   	    		}
   	    	}
   	    	break;

	    case MotionEvent.ACTION_MOVE :
   	    	e_touchX = (int) event.getX();
   	    	e_touchY = (int) event.getY();
            slide_x = e_touchX - s_touchX;
            slide_y = s_touchY - e_touchY;
            if (getslide_x() > 60){
            	slide_x = 60;
            }
            if (getslide_x() < -60){
            	slide_x = -60;
            }
            if (getslide_y() > 60){
            	slide_y = 60;
            }
            if (getslide_y() < -60){
            	slide_y = -60;
            }
            if ((getslide_xsum() <= 60 && getslide_xsum() >=0) || (getslide_xsum() <= 0 && getslide_xsum() >= -60)){
                slide_xsum =getslide_xsum() + getslide_x();
            }
            if ((getslide_ysum() >= 0 && getslide_ysum() <= 60) || (getslide_ysum() <= 0 && getslide_ysum() >= -60)){
                slide_ysum =getslide_ysum() + getslide_y();
            }
            s_touchX = e_touchX;
            s_touchY = e_touchY;

            if (getreach_flg() == true){
		    	s_touchX = 0;
		    	s_touchY = 0;
		    	e_touchX = 0;
		    	e_touchY = 0;
		    	slide_x = 0;
		    	slide_y = 0;
		    	slide_xsum = 0;
		    	slide_ysum = 0;
		    	mode = -1;   
            }
	    	break;

	    case MotionEvent.ACTION_UP :
		    	s_touchX = 0;
		    	s_touchY = 0;
		    	e_touchX = 0;
		    	e_touchY = 0;
		    	slide_x = 0;
		    	slide_y = 0;
		    	slide_xsum = 0;
		    	slide_ysum = 0;
		    	mode = -1;
		    	reach_flg = false;
		    	break;
	    }			

        return true;
    }  

    @Override 
    public boolean onKeyDown(int keyCode,KeyEvent event) {
        slidePiece(keyCode);
        return super.onKeyDown(keyCode,event);
    }
    public int getmode(){
    	return mode;
    }    
    public int getslide_x(){
    	return slide_x;
    }    
    public int getslide_y(){
    	return slide_y;
    }
    public int getslide_xsum(){
    	return slide_xsum;
    }    
    public int getslide_ysum(){
    	return slide_ysum;
    }
    public int gettouchX(){
    	return touchX;
    }
    public int gettouchY(){
    	return touchY;
    }    
    public int getfreeX(){
    	return freeX;
    }
    public int getfreeY(){
    	return freeY;
    }
    public boolean getreach_flg(){
    	return reach_flg;
    }
  private int slide_x;
  private int slide_y;
  private int mode = -1;
  private int touchX;
  private int touchY;
  private int freeX;
  private int freeY;
  private int s_touchX = 0;
    private int s_touchY = 0;
    private int e_touchX = 0;
    private int e_touchY = 0;
    private int slide_xsum = 0;
    private int slide_ysum = 0;
    private boolean reach_flg = false;
}
トラックバック - http://d.hatena.ne.jp/chiakisugimoto/20100324/1269445932
Connection: close