スライドパズルで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; }