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

今日は、GLSurfaceView(OpenGL)で実装した場合のソースコードです。
スライドくらいの動きでは3つの実装による動きの違いを体感することは出来ませんが、もっと早い動きや、動くモジュールが多いアプリでは、GLSurfaceView→SurfaceView→Viewの順で滑らかな動きになります。
メモリ使用量や端末負荷もこの順に高くなるため、アプリの特徴に応じて使い分けます。今回のスライドパズルくらいだと、タッチイベント時のみ計算・再描画を行うViewで十分ということになります。
写真は、このコードによる表示画面。3つのブロックを上方に指でスライドしている時のキャプチャ。

SlidePuzzle.javaは最初のものと変わりませんが、GLSurfaceViewに切り替えるフラグとして、glsurfaceview_flg を真に変更します。

view_flg = false ; surfaceview_flg = false; glsurfaceview_flg = true;

package com.chiaki.example;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.Random;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLSurfaceView;
import android.opengl.GLU;
import android.opengl.GLUtils;
import android.view.KeyEvent;
import android.view.MotionEvent;

public class SlidePuzzle_GLSurfaceView extends GLSurfaceView implements GLSurfaceView.Renderer {
    private Random rand=new Random();
    private Bitmap image;            
    private int[]  data=new int[25]; 
	private FloatBuffer[] vertexBuff = new FloatBuffer[25];
	private FloatBuffer textureBuff = null;
	private int[] textureId;
	
	public SlidePuzzle_GLSurfaceView(Context context) {
		super(context);
        initialize(context);

        for (int i=0;i<25;i++) data[i]=i;
        loadPicture(context);
    }
	
	private void initialize(Context context) {
	    setFocusable(true);      
	    setFocusableInTouchMode(true); 
		setFocusable(true);
		this.setRenderer( this );
		ByteBuffer[] byteBuffer = new ByteBuffer[25];

		for (int i = 0; i < 25; i++){
			byteBuffer[i] = ByteBuffer.allocateDirect(4 * 3 * 4);
			byteBuffer[i].order(ByteOrder.nativeOrder());
			vertexBuff[i] = byteBuffer[i].asFloatBuffer();			
		}
		
		ByteBuffer t_byteBuffer = ByteBuffer.allocateDirect(4 * 2 * 4);
		t_byteBuffer.order(ByteOrder.nativeOrder());
		textureBuff = t_byteBuffer.asFloatBuffer();

		textureBuff.put(new float[] {
				0.0f, 1.0f,		//左下
				1.0f, 1.0f,		//右下
				0.0f, 0.0f,		//左上
				1.0f, 0.0f,		//右上
		});
		textureBuff.position(0);	

        Resources r=context.getResources();
        int resID=R.drawable.picture;
        image = BitmapFactory.decodeResource(r,resID); 
        image =  Bitmap.createScaledBitmap(image, 300, 300, true); 
	}

	private void loadTexture( GL10 gl ){
        int width = image.getWidth();
        int height = image.getHeight();
        int[][] pixels = new int[25][(width/5) * (height/5)+1];
        
        int img_pixels[] = new int[width * height];
        for (int i = 0; i < 25; i++){
            pixels[i] = new int[(width/5) * (height/5)];        	
        }
        image.getPixels(img_pixels, 0, width, 0, 0, width, height);

        for (int y = 0; y < height/5; y++) {
            for (int x = 0; x < width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[0][x + y * (width/5)] = pixel;
            }
            for (int x = width/5; x < 2*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[1][(x - width/5) + y * (width/5)] = pixel;
            }
            for (int x = 2*width/5; x < 3*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[2][(x - 2*width/5) + y * (width/5)] = pixel;
            }
            for (int x = 3*width/5; x < 4*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[3][(x - 3*width/5) + y * (width/5)] = pixel;
            }
            for (int x = 4*width/5; x < width; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[4][(x - 4*width/5) + y * (width/5)] = pixel;
            }
        }
        for (int y = height/5; y < 2*height/5; y++) {
            for (int x = 0; x < width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[5][x + (y - height/5) * (width/5)] = pixel;
            }
            for (int x = width/5; x < 2*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[6][(x - width/5) + (y - height/5) * (width/5)] = pixel;
            }
            for (int x = 2*width/5; x < 3*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[7][(x - 2*width/5) + (y - height/5) * (width/5)] = pixel;
            }
            for (int x = 3*width/5; x < 4*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[8][(x - 3*width/5) + (y - height/5) * (width/5)] = pixel;
            }
            for (int x = 4*width/5; x < width; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[9][(x - 4*width/5) + (y - height/5) * (width/5)] = pixel;
            }
        }
        for (int y = 2*height/5; y < 3*height/5; y++) {
            for (int x = 0; x < width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[10][x + (y - 2*height/5) * (width/5)] = pixel;
            }
            for (int x = width/5; x < 2*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[11][(x - width/5) + (y - 2*height/5) * (width/5)] = pixel;
            }
            for (int x = 2*width/5; x < 3*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[12][(x - 2*width/5) + (y - 2*height/5) * (width/5)] = pixel;
            }
            for (int x = 3*width/5; x < 4*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[13][(x - 3*width/5) + (y - 2*height/5) * (width/5)] = pixel;
            }
            for (int x = 4*width/5; x < width; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[14][(x - 4*width/5) + (y - 2*height/5) * (width/5)] = pixel;
            }
        }
        for (int y = 3*height/5; y < 4*height/5; y++) {
            for (int x = 0; x < width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[15][x + (y - 3*height/5) * (width/5)] = pixel;
            }
            for (int x = width/5; x < 2*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[16][(x - width/5) + (y - 3*height/5) * (width/5)] = pixel;
            }
            for (int x = 2*width/5; x < 3*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[17][(x - 2*width/5) + (y - 3*height/5) * (width/5)] = pixel;
            }
            for (int x = 3*width/5; x < 4*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[18][(x - 3*width/5) + (y - 3*height/5) * (width/5)] = pixel;
            }
            for (int x = 4*width/5; x < width; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[19][(x - 4*width/5) + (y - 3*height/5) * (width/5)] = pixel;
            }
        }
        for (int y = 4*height/5; y < height; y++) {
            for (int x = 0; x < width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[20][x + (y - 4*height/5) * (width/5)] = pixel;
            }
            for (int x = width/5; x < 2*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[21][(x - width/5) + (y - 4*height/5) * (width/5)] = pixel;
            }
            for (int x = 2*width/5; x < 3*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[22][(x - 2*width/5) + (y - 4*height/5) * (width/5)] = pixel;
            }
            for (int x = 3*width/5; x < 4*width/5; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[23][(x - 3*width/5) + (y - 4*height/5) * (width/5)] = pixel;
            }
            for (int x = 4*width/5; x < width; x++) {
                int pixel = img_pixels[x + y * width];
                pixels[24][(x - 4*width/5) + (y - 4*height/5) * (width/5)] = pixel;
            }
        }

        Bitmap[] bitmap = new Bitmap[25];
        for (int i = 0; i < 25; i++){
        	bitmap[i] = Bitmap.createBitmap(width/5, height/5, Bitmap.Config.ARGB_8888);
            bitmap[i].setPixels(pixels[i], 0, width/5, 0, 0, width/5, height/5);                	
            bitmap[i] =  Bitmap.createScaledBitmap(bitmap[i], 128, 128, true); 
        }
        
        int[] textures = new int[25];
        gl.glGenTextures(25, textures, 0);
        image.recycle();	
        textureId = new int[25];
        for (int i = 0; i < 25; i++){
            textureId[i] = textures[i];
            gl.glBindTexture(GL10.GL_TEXTURE_2D, textureId[i]);
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER,
                    GL10.GL_NEAREST);	
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER,
                    GL10.GL_LINEAR);	
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S,
                    GL10.GL_CLAMP_TO_EDGE);	
            gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T,
                    GL10.GL_CLAMP_TO_EDGE);
            gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE,
                    GL10.GL_REPLACE);	        
            GLUtils.texImage2D( GL10.GL_TEXTURE_2D, 0, bitmap[i], 0 );
            bitmap[i].recycle();	
        }
	}

	@Override
    public void onResume(){
    	super.onResume();
    	this.onResume();
    }

    @Override
    public void onPause(){
    	super.onPause();
    	this.onPause();
    }

	@Override
	public void onSurfaceCreated(GL10 gl, EGLConfig config) {
    	gl.glClearColor( 0.0f, 0.0f, 0.0f, 1.0f );	
    	gl.glMatrixMode(GL10.GL_PROJECTION);
        gl.glLoadIdentity();
 
    	gl.glShadeModel( GL10.GL_FLAT );	
    	gl.glEnableClientState( GL10.GL_VERTEX_ARRAY );	
    	gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY );
    	gl.glEnable( GL10.GL_TEXTURE_2D );	
    	  	
	    GLU.gluOrtho2D(gl, -1.0f, 1.0f, -1.0f, 1.0f);
	    
		this.loadTexture( gl );    
		
//		new SlidePuzzle_Graphics2D(gl);		
	}

	@Override
	public void onSurfaceChanged(GL10 gl, int width, int height) {
    	gl.glViewport( 0, 0, width, height );			
	}

	@Override
	public void onDrawFrame(GL10 gl) {
		ByteBuffer[] byteBuffer = new ByteBuffer[25];
		for (int i = 0; i < 25; i++){
	 		byteBuffer[i] = ByteBuffer.allocateDirect(4 * 3 * 4);
			byteBuffer[i].order(ByteOrder.nativeOrder());
			vertexBuff[i] = byteBuffer[i].asFloatBuffer();
		}
		float tl_x = -1.0f;
		float tl_y = -1.0f;
		float tr_x = 1.0f;
		float tr_y = -1.0f;
		float ul_x = -1.0f;
		float ul_y = 1.0f;
		float ur_x = 1.0f;
		float ur_y = 1.0f;
		
		float ratiox = 2.0f/5;
		float ratioy = (2.0f/5)*(320.0f/480.0f);
		tl_x = (ratiox * -0.5f);
		tl_y = (ratioy * -0.5f);
		tr_x = (ratiox * 0.5f);
		tr_y = (ratioy * -0.5f);
		ul_x = (ratiox * -0.5f);
		ul_y = (ratioy * 0.5f);
		ur_x = (ratiox * 0.5f);
		ur_y = (ratioy * 0.5f);
		float [] x = new float[25];
		float [] y = new float[25];
		for (int i = 0; i < 25; i++){
			if (i%5 == 0){
				x[i] = -1.0f;				
			}else if(i%5 == 1){
				x[i] = -1.0f/2.0f;
			}else if(i%5 == 2){
				x[i] = 0;
			}else if(i%5 == 3){
				x[i] = 1.0f/2.0f;
			}else if(i%5 == 4){
				x[i] = 1.0f;
			}
		}	
		for (int i = 0; i < 25; i++){
			if (i/5 == 0){
				y[i] = 1.0f;				
			}else if(i/5 == 1){
				y[i] = 1.0f/2.0f;
			}else if(i/5 == 2){
				y[i] = 0;
			}else if(i/5 == 3){
				y[i] = -1.0f/2.0f;
			}else if(i/5 == 4){
				y[i] = -1.0f;
			}
		}	
		for (int i = 0; i < 25; i++){
	    	if (getmode() == KeyEvent.KEYCODE_DPAD_UP || 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) ||(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)){
	    			vertexBuff[i].put(new float[] {
    		                tl_x+x[i]*(2.0f/2.5f), tl_y+y[i]*(2.0f/2.5f)*(320.0f/480.0f)+(getslide_ysum()*(1.0f/240.0f)), 0.0f,
    		                tr_x+x[i]*(2.0f/2.5f), tl_y+y[i]*(2.0f/2.5f)*(320.0f/480.0f)+(getslide_ysum()*(1.0f/240.0f)), 0.0f,
    		                ul_x+x[i]*(2.0f/2.5f), ul_y+y[i]*(2.0f/2.5f)*(320.0f/480.0f)+(getslide_ysum()*(1.0f/240.0f)), 0.0f,
    		                ur_x+x[i]*(2.0f/2.5f), ur_y+y[i]*(2.0f/2.5f)*(320.0f/480.0f)+(getslide_ysum()*(1.0f/240.0f)), 0.0f});
    				vertexBuff[i].position(0);	    				
	    		}else{
	    			vertexBuff[i].put(new float[] {
    		                tl_x+x[i]*(2.0f/2.5f), tl_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                tr_x+x[i]*(2.0f/2.5f), tr_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                ul_x+x[i]*(2.0f/2.5f), ul_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                ur_x+x[i]*(2.0f/2.5f), ur_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f});
    				vertexBuff[i].position(0);	    				
	    		}
   				int[] textureId_tmp = new int[25];
                if (getslide_ysum() >= 60 || getslide_ysum() <= -60){
                	if (getslide_ysum() >= 60){
           	    		for (int j=touchY;j>freeY;j--) {
           	    			slidePiece(getmode());       	    					
           	    		}                		
                	}else if (getslide_ysum() <= -60){
           	    		for (int j=freeY;j>touchY;j--) {
           	    			slidePiece(getmode());       	    					
           	    		}                		
                	}
       	    		for (int j = 0; j < 25; j++){
       	    			textureId_tmp[j] = textureId[data[j]];
       	    		}
       	    		for (int j = 0; j < 25; j++){
       	    			textureId[j] = textureId[j];
       	    		}
       			    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;
                }
	    	}else if (getmode() == KeyEvent.KEYCODE_DPAD_RIGHT || getmode() == KeyEvent.KEYCODE_DPAD_LEFT){
	    		if ((i < (5*getfreeY() + getfreeX()) && i >= (5*gettouchY() + gettouchX()) && getslide_xsum() <= 60 && getslide_xsum() >= 0) || (i > (5*getfreeY() + getfreeX()) && i <= (5*gettouchY() + gettouchX()) && getslide_xsum() >= -60 && getslide_xsum() <= 0)){
	    			vertexBuff[i].put(new float[] {
    		                tl_x+x[i]*(2.0f/2.5f)+(getslide_xsum()*(1.0f/160.0f)), tl_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                tr_x+x[i]*(2.0f/2.5f)+(getslide_xsum()*(1.0f/160.0f)), tr_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                ul_x+x[i]*(2.0f/2.5f)+(getslide_xsum()*(1.0f/160.0f)), ul_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                ur_x+x[i]*(2.0f/2.5f)+(getslide_xsum()*(1.0f/160.0f)), ur_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f});
    				vertexBuff[i].position(0);	    				
	    		}else{
	    			vertexBuff[i].put(new float[] {
    		                tl_x+x[i]*(2.0f/2.5f), tl_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                tr_x+x[i]*(2.0f/2.5f), tr_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                ul_x+x[i]*(2.0f/2.5f), ul_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
    		                ur_x+x[i]*(2.0f/2.5f), ur_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f});
    				vertexBuff[i].position(0);	    				
	    		}
   				int[] textureId_tmp = new int[25];
                if (getslide_xsum() >= 60 || getslide_xsum() <= -60){
                	if (getslide_xsum() >= 60){
           	    		for (int j=freeX;j>touchX;j--) {
           	    			slidePiece(getmode());       	    					
           	    		}                		
                	}else if (getslide_xsum() <= -60){
           	    		for (int j=touchX;j>freeX;j--) {
           	    			slidePiece(getmode());       	    					
           	    		}                		
                	}
       	    		for (int j = 0; j < 25; j++){
       	    			textureId_tmp[j] = textureId[data[j]];
       	    		}
       	    		for (int j = 0; j < 25; j++){
       	    			textureId[j] = textureId[j];
       	    		}
       			    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;
                }
	    	}else{
    			vertexBuff[i].put(new float[] {
		                tl_x+x[i]*(2.0f/2.5f), tl_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
		                tr_x+x[i]*(2.0f/2.5f), tr_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
		                ul_x+x[i]*(2.0f/2.5f), ul_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f,
		                ur_x+x[i]*(2.0f/2.5f), ur_y+y[i]*((2.0f/2.5f)*(320.0f/480.0f)), 0.0f});
				vertexBuff[i].position(0);	    				
	    	}
		}
		
		gl.glClear( GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT );	
        gl.glActiveTexture( GL10.GL_TEXTURE0 );

        for (int i = 0; i <= 24; i++){
        	if (data[i] == 24){
        		
        	}else{
        		gl.glBindTexture( GL10.GL_TEXTURE_2D, textureId[data[i]] );
                gl.glPushMatrix();
        		gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuff[i] );
        		gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
            	gl.glEnableClientState( GL10.GL_TEXTURE_COORD_ARRAY );	
            	gl.glEnable( GL10.GL_TEXTURE_2D );	
        		gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, textureBuff );
        		gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP,0,4);
        		gl.glPopMatrix();        		
        	}
        }
	}

    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 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;
	    }			

        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;
}