スライドパズルでViewとSurfaceViewとOpenGL(GLSurfaceView)を比較 その2

今日はViewを使ったソースコード。次回OpenGL版のソースコード、次々回とその次で、解説とeclipseにそのままインポートして使えるプロジェクトをアップします。
写真は、このソースでの表示画面。2ブロックを指で左へスライドさせている時のキャプチャです。

SlidePuzzle.javaは前回と変わりませんが、前回のSurfaceViewからViewに切り替えるフラグとして、view_flgを真に変更します。
view_flg = false → true; surfaceview_flg = true → false; glsurfaceview_flg = false → false;

package com.chiaki.example;

import android.content.res.Resources;
import android.content.Context;
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.View;
import java.util.Random;

public class SlidePuzzle_View extends View {
  private Random rand=new Random();
    private Bitmap image;            
    private int[]  data=new int[25]; 

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

        for (int i=0;i<25;i++) data[i]=i;
        loadPicture(context);
    }
	
  private void initialize() {
	setBackgroundColor(Color.WHITE);
	setFocusable(true);      
	setFocusableInTouchMode(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]);
        }        
        invalidate();
    }

    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 
    protected void onDraw(Canvas canvas) {
	    drawPuzzle(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;   
//		    	reach_flg = false;
            }
	    	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;
	    }			
	    invalidate();
        return true;
    }  

    @Override 
    public boolean onKeyDown(int keyCode,KeyEvent event) {
        slidePiece(keyCode);
        invalidate();
        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;
}