Android拼图游戏 玩转从基础到应用手势变化

相信大家在小的时候都玩过拼图游戏,现如今,手机普及,能在手机上玩的游戏越来越多,于是乎,重温小时候,编写这个简易拼图游戏,而且也能进一步加深Android的一些基础知识。
老规矩,先是效果图:

这里我把为了演示效果,把图片打乱的很少,在代码里可以更改。

首先,有个默认的图片,可以用来拼图,也可以选择你喜欢的图片进行拼图,拼图的过程会记录移动的步数,并且当游戏胜利的时候会弹出一个笑脸提示,游戏胜利,用了多少步数。

ps:感兴趣的完全可以继续在这上面进行扩展,比如增加游戏难度的选项,可以将图片分成更多的小方块等等。

大体思路:将大图切割成各个小方块,用数组记录每个小方块的信息,用GridLayout来显示各个小方块,并且将某个小方块标记为空白方块(空白方块可以和相邻方块进行交换),在GridLayout上的各个小方块上增加点击事件和在整个屏幕上添加手势事件,每次点击或者有手势时,判断小方块是否能移动,最后在游戏胜利时弹出胜利提示。
话不多说,接下来,就是一步步实现拼图游戏的过程啦。

1.小方块相关的类。

这是小方块的各种变量的item,类,用来管理将大图切割成每个小方块的每个小方块的信息。很简单,就是各种变量和Setter和Getter方法直接上代码~

/** * Created by yyh on 2016/10/21. */ public class GameItemView{ /** * 每个小方块的信息 */ //每个小方块的实际位置x, private int x=0; //每个小方块的实际位置y, private int y=0; //每个小方块的图片, private Bitmap bm; //每个小方块的图片位置x, private int p_x=0; //每个小方块的图片位置y. private int p_y=0; public GameItemView(int x, int y, Bitmap bm) { super(); this.x = x; this.y = y; this.bm = bm; this.p_x=x; this.p_y=y; } public int getX() { return x; } public void setX(int x) { this.x = x; } public int getY() { return y; } public Bitmap getBm() { return bm; } public void setBm(Bitmap bm) { this.bm = bm; } public int getP_x() { return p_x; } public void setP_x(int p_x) { this.p_x = p_x; } public int getP_y() { return p_y; } public void setP_y(int p_y) { this.p_y = p_y; } /** * 判断每个小方块的位置是否正确 * @return */ public boolean isTrue(){ if (x==p_x&&y==p_y){ return true; } return false; } }

2.主界面的布局

主界面很简单,一个Button,用来换图片,一个ImageView,用来显示原图,一个GridLayout用来进行拼图游戏,最后,一个TextView,用来显示完成这个拼图用了多少步数。布局如下:

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" > <LinearLayout android:id="@+id/ll" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/bt_choice" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="选择图片" android:adjustViewBounds="true" /> </LinearLayout> <ImageView android:id="@+id/iv" android:layout_below="@id/ll" android:adjustViewBounds="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/haizei" android:layout_marginTop="3dp" ></ImageView> <!-- 游戏的主界面--> <GridLayout android:layout_marginTop="3dp" android:layout_below="@id/iv" android:id="@+id/gl" android:layout_width="wrap_content" android:layout_height="wrap_content" android:columnCount="5" android:rowCount="3" android:adjustViewBounds="true" > </GridLayout> <TextView android:id="@+id/tv_step" android:layout_below="@id/gl" android:layout_marginTop="3dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="已用步数:0" android:textSize="26sp" /> </RelativeLayout>

3.打开图片选择图片

给Button设置点击事件,调用startActivityForResult(Intent intent,int requestCode);方法,来获取图片。

bt_choice.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent= new Intent("android.intent.action.GET_CONTENT"); intent.setType("image/*"); startActivityForResult(intent, CHOICE_PHOTO);//打开相册 } });

在Activity中重写onActivityResult(int requestCode, int resultCode, Intent data)方法来显示选择的图片,以及初始化游戏。(图片选择完以后,就要进行图片的切割,和拼图游戏的开始。)

protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); switch (requestCode){ case CHOICE_PHOTO: if (resultCode==RESULT_OK){ //判断手机系统版本 if (Build.VERSION.SDK_INT>=19){ handleImageOnKitKat(data); //得到imageview中的图片 BitmapDrawable bitmapDrawable= (BitmapDrawable) photo.getDrawable(); bt_tupan=bitmapDrawable.getBitmap(); //将原来GridLayout中的小方块移除, removeGameItem(); //将新图切割成小方块并加入GridLayout. setGameItem(); //开始游戏 startGame(); }else { handleImageBeforeKitKat(data); //得到imageview中的图片 BitmapDrawable bitmapDrawable= (BitmapDrawable) photo.getDrawable(); bt_tupan=bitmapDrawable.getBitmap(); //将原来GridLayout中的小方块移除, removeGameItem(); //将新图切割成小方块并加入GridLayout. setGameItem(); //开始游戏 startGame(); } } } }

然后是选择图片的具体方法的实现函数。注释很清楚,不多说。我们的重点在拼图以及手势变化的具体实现,这里选择图片的方式很多。不多讲,网上有现成的框架。

//手机不大于19的取数据方法 private void handleImageBeforeKitKat(Intent data) { Uri uri =data.getData(); String imagePath = getImagePath(uri, null); displayImage(imagePath); } /** * 手机大于19的取数据方法 * @param data */ @TargetApi(Build.VERSION_CODES.KITKAT) private void handleImageOnKitKat(Intent data) { String imagePath=null; Uri uri=data.getData(); if (DocumentsContract.isDocumentUri(this,uri)){ //如果是document类型的url,则通过document的id处理。 String docId=DocumentsContract.getDocumentId(uri); if ("com.android.providers.media.documents".equals(uri.getAuthority())){ String id =docId.split(":")[1];//解析出数字格式的id; String selection= MediaStore.Images.Media._ID+"="+id; imagePath=getImagePath(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,selection); }else if ("com.android.providers.downloads.documents".equals(uri.getAuthority())){ Uri contenturi= ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"),Long.valueOf(docId)); imagePath=getImagePath(contenturi,null); } }else if ("content".equalsIgnoreCase(uri.getScheme())){ //如果不是document类型的uri,则使用普通的方式处理。 imagePath=getImagePath(uri,null); } displayImage(imagePath); } /** * 显示图片 * @param imagePath //图片的路径。 */ private void displayImage(String imagePath) { if (imagePath != null) { Bitmap bitmap = BitmapFactory.decodeFile(imagePath); if (isHeigthBigWidth(bitmap)) { Bitmap bt = rotaingImageView(bitmap);//将图片旋转90度。 Bitmap disbitmapt = ajustBitmap(bt); photo.setImageBitmap(disbitmapt); } else { Bitmap disbitmap = ajustBitmap(bitmap); photo.setImageBitmap(disbitmap); } } } /** * 调整图片的方向 * @param bitmap * @return */ private Bitmap rotaingImageView(Bitmap bitmap) { //旋转图片 动作 Matrix matrix = new Matrix();; matrix.postRotate(270); // 创建新的图片 Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true); return resizedBitmap; } /** * 得到图片的路径 * @param externalContentUri * @param selection * @return */ private String getImagePath(Uri externalContentUri, String selection) { String path=null; Cursor cursor=getContentResolver().query(externalContentUri, null, selection, null, null); if (cursor!=null){ if (cursor.moveToFirst()){ path=cursor.getString(cursor.getColumnIndex(MediaStore.Images.Media.DATA)); } } cursor.close(); return path; }

4.拼图的各个小方块的形成过程。

看着各个小方块,我们用GridLayout来实现是最为方便的。所以,用一个GridLayout来显示大图切割后的各个小方块,用一个ImageView数组来保存各个小方块的信息,并且,我们默认把最后一个小方块设置为空白方块。

首先是各种需要的变量。注释很清楚。

/** * 利用二维数组创建若干个游戏小方框 */ private ImageView [][] iv_game_arr=new ImageView[3][5]; /** *游戏主界面 * */ private GridLayout gl_game_layout; //小方块的行和列 private int i; private int j; /**空方块的全局变量*/ private ImageView iv_null_imagview;

接着是从Imageview获取图片,并且将图片按照一定的行和列进行切割(这里将拼图设置为3行5列)。将切割后的各个小方块的信息保存在一个ImageView数组中。给每个小方块设置Tag,和点击监听。

private void setGameItem() { //调整图片的尺寸 Bitmap abitmap=ajustBitmap(bt_tupan); int ivWidth=getWindowManager().getDefaultDisplay().getWidth()/5;//每个游戏小方块的宽和高。切成正方形 int tuWidth=abitmap.getWidth()/5; for (int i=0;i<iv_game_arr.length;i++){ for (int j=0;j<iv_game_arr[0].length;j++){ //将大图切成小方块 Bitmap bm=Bitmap.createBitmap(abitmap,j*tuWidth,i*tuWidth,tuWidth,tuWidth); iv_game_arr[i][j]=new ImageView(this); iv_game_arr[i][j].setImageBitmap(bm);//设置每一个小方块的图案 iv_game_arr[i][j].setLayoutParams(new RelativeLayout.LayoutParams(ivWidth, ivWidth)); //设置方块之间的间距 iv_game_arr[i][j].setPadding(2, 2, 2, 2); iv_game_arr[i][j].setTag(new GameItemView(i, j, bm)); //绑定自定义数据 iv_game_arr[i][j].setOnClickListener(new View.OnClickListener() { ....... );

当然,我们选择的图片不可能都是符合标准的大小的,所以,在切割图片之前我们要对图片进行调整。将图片调整为5:3的比例。(这样切割成3行5列的小方块才能正确切割)这里对于width,我把每个小方块的间隔事先也算到里面去。

//调整图片的大小 private Bitmap ajustBitmap(Bitmap bitmap) { int width=getWindowManager().getDefaultDisplay().getWidth()-(iv_game_arr[0].length-1)*2; int heigth=width/5*3; Bitmap scaledBitmap=Bitmap.createScaledBitmap(bitmap, width, heigth, true); return scaledBitmap; }

将每个小方格放入到GridLayout中。

/** * 将小方格放入GridLayout */ private void startGame() { tv_step.setText("已用步数:0"); for (i = 0; i <iv_game_arr.length; i++){ for (j = 0; j <iv_game_arr[0].length; j++){ gl_game_layout.addView(iv_game_arr[i][j]); } } //将最后一个方块设置为设置空方块。 setNullImageView(iv_game_arr[i-1][j-1]);

5.小方块的点击事件和手势判断过程。

这里是拼图游戏的核心,弄懂了小方块的移动变化规律,也就弄懂了拼图游戏。

对于点击事件,首先拿到被点击的小方块的各种信息(位置、图案)和空白小方块的位置信息,判断被点击的小方块是否和空白小方块相邻,如果相邻,就移动交换数据(用TranslateAnimation来实现移动动画),如果不相邻则无操作。
a.判断点击方块和空白方块是否相邻的方法

/** * 判断当前点击的方块,是否和空方块相邻。 * @param imageView 当前点击的方块 * @return true:相邻。 false:不相邻。 */ public boolean isAdjacentNullImageView(ImageView imageView){ //获取当前空方块的位置与点击方块的位置 GameItemView null_gameItemView= (GameItemView) iv_null_imagview.getTag(); GameItemView now_gameItem_view = (GameItemView) imageView.getTag(); if(null_gameItemView.getY()==now_gameItem_view.getY()&&now_gameItem_view.getX()+1==null_gameItemView.getX()){//当前点击的方块在空方块的上面 return true; }else if(null_gameItemView.getY()==now_gameItem_view.getY()&&now_gameItem_view.getX()==null_gameItemView.getX()+1){//当前点击的方块在空方块的下面 return true; }else if(null_gameItemView.getY()==now_gameItem_view.getY()+1&&now_gameItem_view.getX()==null_gameItemView.getX()){//当前点击的方块在空方块的左面 return true; }else if(null_gameItemView.getY()+1==now_gameItem_view.getY()&&now_gameItem_view.getX()==null_gameItemView.getX()){ ////当前点击的方块在空方块的右面 return true; } return false; }

b.接着是如果相邻就进入方块数据交换的方法
这里有个方法重载,是否需要动画效果,没有动画效果的数据交换是为初始化游戏时打乱拼图做准备的。这里将核心交换代码列出。每次交换后还要判断是否游戏胜利(即是否拼图完成~)。

//得到点击方块绑定的数据 GameItemView gameItemView = (GameItemView) itemimageView.getTag(); //将空方块的图案设置为点击方块 iv_null_imagview.setImageBitmap(gameItemView.getBm()); //得到空方块绑定的数据 GameItemView null_gameItemView = (GameItemView) iv_null_imagview.getTag(); //交换数据(将点击方块的数据传入空方块) null_gameItemView.setBm(gameItemView.getBm()); null_gameItemView.setP_x(gameItemView.getP_x()); null_gameItemView.setP_y(gameItemView.getP_y()); //设置当前点击的方块为空方块。 setNullImageView(itemimageView); if (isStart){ isGameWin();//成功时,会弹一个吐司。 }

c.交换时的动画设置
交换设置动画时,首先判断移动的方向,根据方向设置不同的移动动画,然后再监听动画完成后,进行数据交换操作。即上面b.接着是如果相邻就进入方块数据交换的方法.最后执行动画。

//1.创建一个动画,设置方向,移动的距离 //判断方向,设置动画 if (itemimageView.getX()>iv_null_imagview.getX()){//当前点击的方块在空方块的上面 //下移 translateAnimation = new TranslateAnimation(0.1f,-itemimageView.getWidth(),0.1f,0.1f); }else if (itemimageView.getX()<iv_null_imagview.getX()){//当前点击的方块在空方块的下面 //上移 boolean f=itemimageView.getX()<iv_null_imagview.getX(); //Log.i("点击方块","sssssssssssssssssssssssss"+f); translateAnimation = new TranslateAnimation(0.1f,itemimageView.getWidth(),0.1f,0.1f); }else if (itemimageView.getY()>iv_null_imagview.getY()){//当前点击的方块在空方块的左面 //右移 translateAnimation=new TranslateAnimation(0.1f,0.1f,0.1f,-itemimageView.getWidth()); }else if(itemimageView.getY()<iv_null_imagview.getY()){//当前点击的方块在空方块的右面 //左移 translateAnimation=new TranslateAnimation(0.1f,0.1f,0.1f,itemimageView.getWidth()); } //2.设置动画的各种参数 translateAnimation.setDuration(80); translateAnimation.setFillAfter(true); //3.设置动画的监听 translateAnimation.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { isAminMove=true; } @Override public void onAnimationEnd(Animation animation) { //动画结束,交换数据 ...... } //动画执行 itemimageView.startAnimation(translateAnimation);

点击事件的流程就完了,接下来是手势判断的事件。即不仅可以通过点击小方块进行移动,也可以通过手势移动小方块。

One.创建手势对象
在onFling方法中完成手势相关的操作。

//创建手势对象 gestureDetector =new GestureDetector(this, new GestureDetector.OnGestureListener() { @Override public boolean onDown(MotionEvent e) { return false; } @Override public void onShowPress(MotionEvent e) { } @Override public boolean onSingleTapUp(MotionEvent e) { return false; } @Override public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public void onLongPress(MotionEvent e) { } @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { //手势相关的操作 ...... }

接着我们onFling方法中做具体操作

Two.判断手势移动的方向
根据返回值的不同得到不同的移动方向。

/** * 增加手势滑动,根据手势判断是上下左右滑动 * @param start_x 手势起始点x * @param start_y 手势起始点y * @param end_x 手势终止点 x * @param end_y 手势终止点y * @return 1:上 2:下 3:左 4:右 */ public int getDirctionByGesure(float start_x,float start_y,float end_x,float end_y){ boolean isLeftOrRight =(Math.abs(end_x-start_x)>Math.abs(end_y-start_y))?true:false; //是否是左右 if(isLeftOrRight){//左右 boolean isLeft=(end_x-start_x)>0?false:true; if(isLeft){ return 3; }else { return 4; } }else{//上下 boolean isUp=(end_y-start_y)>0?false:true; if (isUp){ return 1; }else { return 2; } } }

Three.根据空方块和移动的方向,判断能否移动以及进行移动操作。
因为是手势,移动的肯定是空方块周围的方块,所以重点就是要判断空方块在要移动的方块的那个方向,再根据方向判断能否移动,进行移动操作。(其中changeDateByImageView()中的方法就是具体的方块交换数据及移动的操作。就是点击事件的那个方法。)

/**重载changeByDirGes(int type)方法; * 根据手势的方向,对空方块相邻位置的方块进行移动。 * @param type 方向的返回值 1:上 2:下 3:左 5:右 * @param isAnim 是否有动画 true:有动画,false:无动画 */ public void changeByDirGes(int type,boolean isAnim){ //1.获取当前空方块的位置。 GameItemView null_gameItemView= (GameItemView) iv_null_imagview.getTag(); int new_x=null_gameItemView.getX(); int new_y=null_gameItemView.getY(); //2.根据方向,设置相应相邻的位置坐标。 if (type==1){//说明空方块在要移动的方块的上面。 new_x++; }else if (type==2){//空方块在要移动的方块的下面 new_x--; }else if (type==3){//空方块在要移动的方块的左面 new_y++; }else if (type==4){//空方块在要移动的方块的右面 new_y--; } //3.判断这个新坐标是否存在 if(new_x>=0&&new_x<iv_game_arr.length&&new_y>=0&&new_y<iv_game_arr[0].length){ //存在,可以移动交换数据 if(isAnim){//有动画 changeDateByImageView(iv_game_arr[new_x][new_y]); }else{ changeDateByImageView(iv_game_arr[new_x][new_y],isAnim); } }else{ //什么也不做 } }

好了,手势事件也就大功告成了~

当然这里有两个要注意的地方。1.首先要对当前的Activity设置onTouchEvent()方法,将onTouch事件交由手势去处理,其次也要设置dispatchTouchEvent()方法,在里面也要向下分发给手势事件,如果不设置向下分发给手势判断,那么在GridLayout里,就只能触发点击事件而手势事件就不会起作用了。2.要增加一个是否在移动过程中的flag,如果在移动过程中,就什么也不做,要不然每次点击小方块即使在移动过程中,也会触发点击事件从而又进行动画移动,造成不好的用户体验。

@Override public boolean onTouchEvent(MotionEvent event) { return gestureDetector.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { gestureDetector.onTouchEvent(ev); return super.dispatchTouchEvent(ev); }

6.游戏开始打乱方块以及游戏结束时弹出Toast提示的方法。

代码很简单,直接上代码,其中,弹出的Toast是一个带有自定义View动画的Toast.

//随机打乱图片的顺序 public void randomOrder(){ //打乱的次数,为了测试方便,设置很小。 for (int i=0;i<5;i++){ //根据手势,交换数据,无动画。 int type = (int) (Math.random()*4)+1; // Log.i("sssssssssfdfdfd","交换次数"+i+"type的值"+type); changeByDirGes(type, false); } } /** * 判断游戏结束的方法 */ public void isGameWin(){ //游戏胜利标志 boolean isGameWin =true; //遍历每个小方块 for (i = 0; i <iv_game_arr.length; i++){ for (j = 0; j <iv_game_arr[0].length; j++){ //为空的方块不判断 跳过 if (iv_game_arr[i][j]==iv_null_imagview){ continue; } GameItemView gameItemView= (GameItemView) iv_game_arr[i][j].getTag(); if (!gameItemView.isTrue()){ isGameWin=false; //跳出内层循环 break; } } if (!isGameWin){ //跳出外层循环 break; } } //根据一个开关变量觉得游戏是否结束,结束时给提示。 if (isGameWin){ // Toast.makeText(this,"游戏胜利",Toast.LENGTH_SHORT).show(); ToastUtil.makeText(this,"恭喜你,游戏胜利,用了"+step+"步",ToastUtil.LENGTH_SHORT,ToastUtil.SUCCESS); step=0; } }

好了,重要的部分都已经完了,这里还有个自定义View的Toast,关于Toast的详解,将在下篇文章,这里先简单说明下自定义Toast的实现过程。
首先,新建一个SuccessToast类,(笑脸包括左眼,有眼,笑脸弧)。我们将核心的过程给出。利用动画,实现动态笑脸画制过程。

@Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); mPaint.setStyle(Paint.Style.STROKE); //话笑脸弧 canvas.drawArc(rectF, 180, endAngle, false, mPaint); mPaint.setStyle(Paint.Style.FILL); if (isSmileLeft) { //如果是左眼,画左眼 canvas.drawCircle(mPadding + mEyeWidth + mEyeWidth / 2, mWidth / 3, mEyeWidth, mPaint); } if (isSmileRight) { //如果是有眼,画右眼。 canvas.drawCircle(mWidth - mPadding - mEyeWidth - mEyeWidth / 2, mWidth / 3, mEyeWidth, mPaint); } } /** * 开始动画的方法 * @param startF 起始值 * @param endF 结束值 * @param time 动画的时间 * @return */ private ValueAnimator startViewAnim(float startF, final float endF, long time) { //设置valueAnimator 的起始值和结束值。 valueAnimator = ValueAnimator.ofFloat(startF, endF); //设置动画时间 valueAnimator.setDuration(time); //设置补间器。控制动画的变化速率 valueAnimator.setInterpolator(new LinearInterpolator()); //设置监听器。监听动画值的变化,做出相应方式。 valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { mAnimatedValue = (float) valueAnimator.getAnimatedValue(); //如果value的值小于0.5 if (mAnimatedValue < 0.5) { isSmileLeft = false; isSmileRight = false; endAngle = -360 * (mAnimatedValue); //如果value的值在0.55和0.7之间 } else if (mAnimatedValue > 0.55 && mAnimatedValue < 0.7) { endAngle = -180; isSmileLeft = true; isSmileRight = false; //其他 } else { endAngle = -180; isSmileLeft = true; isSmileRight = true; } //重绘 postInvalidate(); } }); if (!valueAnimator.isRunning()) { valueAnimator.start(); } return valueAnimator; }

然后新建一个success_toast_layout.xml,完成toast的布局。布局是左右(左边笑脸view,右边TextView的提示。)

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/root_layout" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="#00000000" android:orientation="vertical"> <LinearLayout android:id="@+id/base_layout" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="25dp" android:layout_marginLeft="30dp" android:layout_marginRight="30dp" android:layout_marginTop="25dp" android:background="@drawable/background_toast" android:orientation="horizontal"> <LinearLayout android:id="@+id/linearLayout" android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center"> <com.example.yyh.puzzlepicture.activity.Util.SuccessToast android:id="@+id/successView" android:layout_width="50dp" android:layout_height="50dp" android:layout_gravity="center_vertical|left" android:layout_margin="10px" android:gravity="center_vertical|left" /> </LinearLayout> <TextView android:id="@+id/toastMessage" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:padding="10dp" android:text="New Text" /> </LinearLayout> </LinearLayout>

最后新建一个ToastUtil类,管理自定义的Toast.

/** * Created by yyh on 2016/10/25. */ public class ToastUtil { public static final int LENGTH_SHORT = 0; public static final int LENGTH_LONG = 1; public static final int SUCCESS = 1; static SuccessToast successToastView; public static void makeText(Context context, String msg, int length, int type) { Toast toast = new Toast(context); switch (type) { case 1: { View layout = LayoutInflater.from(context).inflate(R.layout.success_toast_layout, null, false); TextView text = (TextView) layout.findViewById(R.id.toastMessage); text.setText(msg); successToastView = (SuccessToast) layout.findViewById(R.id.successView); successToastView.startAnim(); text.setBackgroundResource(R.drawable.success_toast); text.setTextColor(Color.parseColor("#FFFFFF")); toast.setView(layout); break; } } toast.setDuration(length); toast.show(); } }

这样就可以在ManiActivity中调用这个自定义Toast了。
好了,完结。

游戏源码:拼图游戏的实现过程
gitHub:拼图游戏。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

时间: 2024-10-26 12:16:27

Android拼图游戏 玩转从基础到应用手势变化的相关文章

Android拼图游戏 玩转从基础到应用手势变化_Android

相信大家在小的时候都玩过拼图游戏,现如今,手机普及,能在手机上玩的游戏越来越多,于是乎,重温小时候,编写这个简易拼图游戏,而且也能进一步加深Android的一些基础知识. 老规矩,先是效果图: 这里我把为了演示效果,把图片打乱的很少,在代码里可以更改. 首先,有个默认的图片,可以用来拼图,也可以选择你喜欢的图片进行拼图,拼图的过程会记录移动的步数,并且当游戏胜利的时候会弹出一个笑脸提示,游戏胜利,用了多少步数. ps:感兴趣的完全可以继续在这上面进行扩展,比如增加游戏难度的选项,可以将图片分成更

Android拼图游戏的设计逻辑,从切图到交互动画,从关卡到倒计时,实例提高!

Android拼图游戏的设计逻辑,从切图到交互动画,从关卡到倒计时,实例提高! 群英传的最后一章,我大致的看了一下这个例子,发现鸿洋大神也做过,就参考两个人的设计逻辑,感觉都差不多,就这样实现起来了 一.切图工具类 我们九宫格嘛,肯定要一个切图的工具,把一个图片给切成九张,那具体是怎么实现呢?我们先写一个bean来存储一切的状态 ImagePiece package com.lgl.ninegame.utils; import android.graphics.Bitmap; /** * * C

Android拼图游戏开发全纪录0

最近刚完成一个Android的小项目--拼图游戏.项目并不复杂,但也是一个完整的项目,用到的知识点还是比较丰富的. 做完之后照例进行下总结: 需求定义: 1.选择图片后进入拼图界面,可以选择默认图片或者自定义图片,即从图库选择或者从相机拍照. 2.可以设置游戏的难度,即选择拼图为NXN结构. 3.自动打乱拼图的顺序,利用倒置和算法,确保生成的数据有解. 4.拼图过程中可以查看原图. 5.拼图具有计时.记步功能. 6.完成拼图后显示全部图片并提升拼图成功. 7.可以查看历史记录. *8.利用IDA

Android拼图游戏开发全纪录2

今天我们主要来讨论下拼图游戏的可行性解的问题,其实不要小看拼图游戏,他其实是人工智能算法中很著名的15puzzle问题,网上已经有很多关于这个问题的解释,我就做个搬运工好了. 随机生成的15puzzle大约有%50是无解的,本文将就随机生成的谜题的可解性加以讨论. 设有如下矩阵: 12 1 10 2 7 11 4 14 5 x 9 15 8 13 6 3 将其排成水平的,有:12,1,10,2,7,11,4,14,5,X,9,15,8,13,6,3.并记该序列为A 定义:"倒置变量值"

Android拼图游戏开发全纪录5

今天我们终于可以把这个项目给结束掉啦,有了前几天的准备,相信最后一天还是比较轻松的,国际惯例: 最后要完成的就是我们的主要功能--拼图界面. 布局比较简单,在前几天就已经做好了,现在我们要做的是以下几件事情: 1.计时记步:这个是游戏基本都有的功能,其实也比较简单,记录成功移动的步数.显示一个计时器就行了. 2.处理图片,调整为合适的大小比例:这个方法在前几天已经实现了 3.点击GridView后移动图片:是否能移动的方法已经在前几天实现了 4.判断是否拼图完成:唉,也已经实现了 5.点击原图按

Android拼图游戏开发全纪录3

今天我们要继续开发Android游戏拼图,今天同样是做一些准备工作,昨天我们把界面的准备工作做好了,今天呢,我们想想,要完成一个拼图,我们还需要做哪些准备. 首先,我们需要一个工具类,去获取屏幕的相关信息,让我们的程序去自动适应不同分辨率大小的屏幕: package com.xys.xpuzzle.util; import android.content.Context; import android.util.DisplayMetrics; import android.view.Displa

Android拼图游戏开发全纪录4

今天我们主要实现我们的主界面:国际惯例: 界面我们已经在第一天做好了,今天我们就要实现这个界面的功能, 分析一下,这个界面包含以下几个功能: 1.显示游戏的难度:使用popupwindow,选择后改变显示的数字 2.显示默认的待拼图图片,包含一张选择自定义的图片:这个比较简单,只是GridView的最简单应用而已 3.自定义按钮功能:调用系统图册和相机 4.查看记录和了解更多:这个也是一般的应用需求,比较简单 package com.xys.xpuzzle.activity; import ja

JAVA实现拼图游戏

效果图如下: 源码如下:   package org.test;/*** <p>Title: LoonFramework</p>* <p>Description:拼图图像处理[未优化]</p>* <p>Copyright: Copyright (c) 2007</p>* <p>Company: LoonFramework</p>* @author chenpeng * @email:ceponline@yaho

Android实现美女拼图游戏详解_Android

先来看看效果: 图片切分很多份,点击交换拼成一张完整的:这样关卡也很容易设计,3 3:4 4:5 5:6 6:一直下去 加了个切换动画,效果还是不错的,其实游戏就是自定义了一个控件,下面我们开始自定义之旅. 游戏的设计 首先我们分析下如何设计这款游戏: 1.我们需要一个容器,可以放这些图片的块块,为了方便,我们准备使用RelativeLayout配合addRule实现 2.每个图片的块块,我们准备使用ImageView 3.点击交换,我们准备使用传统的TranslationAnimation来实