Android利用ViewDragHelper轻松实现拼图游戏的示例

前言

最近一段时间看了一些介绍ViewDragHelper的博客,感觉这是一个处理手势滑动的神奇,看完以后就想做点东西练练手,于是就做了这个Android拼图小游戏。

先上个效果图

源码 https://github.com/kevin-mob/Puzzle

ViewDragHelper

其实ViewDragHelper并不是第一个用于分析手势处理的类,gesturedetector也是,但是在和拖动相关的手势分析方面gesturedetector只能说是勉为其难。

关于ViewDragHelper有如下几点:

ViewDragHelper.Callback是连接ViewDragHelper与view之间的桥梁(这个view一般是指拥子view的容器即parentView);

ViewDragHelper的实例是通过静态工厂方法创建的;

你能够指定拖动的方向;

ViewDragHelper可以检测到是否触及到边缘;

ViewDragHelper并不是直接作用于要被拖动的View,而是使其控制的视图容器中的子View可以被拖动,如果要指定某个子view的行为,需要在Callback中想办法;

ViewDragHelper的本质其实是分析onInterceptTouchEvent和onTouchEvent的MotionEvent参数,然后根据分析的结果去改变一个容器中被拖动子View的位置( 通过offsetTopAndBottom(int offset)和offsetLeftAndRight(int offset)方法 ),他能在触摸的时候判断当前拖动的是哪个子View;

虽然ViewDragHelper的实例方法 ViewDragHelper create(ViewGroup forParent, Callback cb) 可以指定一个被ViewDragHelper处理拖动事件的对象 。

实现思路

  1. 自定义PuzzleLayout继承自RelativeLayout。
  2. 将PuzzleLayout的onInterceptTouchEvent和onTouchEvent交给ViewDragHelper来处理。
  3. 将拼图Bitmap按九宫格切割,生成ImageView添加到PuzzleLayout并进行排列。
  4. 创建ImageView的对应数据模型。
  5. ViewDragHelper.Callback控制滑动边界的实现。
  6. 打乱ImageView的摆放位置。

下面介绍一下以上5步的具体实现细节。

第一步: 创建一个PuzzleLayout继承自RelativeLayout。

public class PuzzleLayout extends RelativeLayout {
 public PuzzleLayout(Context context) {
   super(context);
  }

  public PuzzleLayout(Context context, AttributeSet attrs) {
   super(context, attrs);
  }

  public PuzzleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
  }
}

第二步:将PuzzleLayout的onInterceptTouchEvent和onTouchEvent交给ViewDragHelper来处理。

这里我们会用到ViewDragHelper这个处理手势滑动的神器。
在使用之前我们先简单的了解一下它的相关函数。

/**
 * Factory method to create a new ViewDragHelper.
 *
 * @param forParent Parent view to monitor
 * @param sensitivity Multiplier for how sensitive the helper
 * should be about detecting the start of a drag.
 * Larger values are more sensitive. 1.0f is normal.
 * @param cb Callback to provide information and receive events
 * @return a new ViewDragHelper instance
 */
public static ViewDragHelper create(ViewGroup forParent, float sensitivity, Callback cb)

上面这个是创建一个ViewDragHelper的静态函数,根据注释我们可以了解到:

  1. 第一个参数是当前的ViewGroup。
  2. 第二个参数是检测拖动开始的灵敏度,1.0f为正常值。
  3. 第三个参数Callback,是ViewDragHelper给ViewGroup的回调。

这里我们主要来看看Callback这个参数,Callback会在手指触摸当前ViewGroup的过程中不断返回解析到的相关事件和状态,并获取ViewGroup返回给ViewDragHelper的状态,来决定接下来的操作是否需要执行,从而达到了在ViewGroup中管理和控制ViewDragHelper的目的。

Callback的方法很多,这里主要介绍本文用到的几个方法

public abstract boolean tryCaptureView(View child, int pointerId)

尝试捕获当前手指触摸到的子view, 返回true 允许捕获,false不捕获。

public int clampViewPositionHorizontal(View child, int left, int dx)

控制childView在水平方向的滑动,主要用来限定childView滑动的左右边界。

public int clampViewPositionVertical(View child, int top, int dy)

控制childView在垂直方向的滑动,主要用来限定childView滑动的上下边界。

public void onViewReleased(View releasedChild, float xvel, float yvel)

当手指从childView上离开时回调。

有了以上这些函数,我们的拼图游戏大致就可以做出来了,通过ViewDragHelper.create()来创建一个ViewDragHelper,通过Callback中tryCaptureView来控制当前触摸的子view是否可以滑动,clampViewPositionHorizontal、clampViewPositionVertical来控制水平方向和垂直方向的移动边界,具体的方法实现会在后面讲到。

public class PuzzleLayout extends RelativeLayout {
  private ViewDragHelper viewDragHelper;
  public PuzzleLayout(Context context) {
    super(context);
    init();
  }

  public PuzzleLayout(Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
  }

  public PuzzleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
  }

  private void init() {
    getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
      @Override
      public boolean onPreDraw() {
        mHeight = getHeight();
        mWidth = getWidth();
        getViewTreeObserver().removeOnPreDrawListener(this);
        if(mDrawableId != 0 && mSquareRootNum != 0){
          createChildren();
        }
        return false;
      }
    });
    viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
      @Override
      public boolean tryCaptureView(View child, int pointerId) {
        return true;
      }

      @Override
      public int clampViewPositionHorizontal(View child, int left, int dx) {

        return left;
      }

      @Override
      public int clampViewPositionVertical(View child, int top, int dy) {
        return top;
      }

      @Override
      public void onViewReleased(View releasedChild, float xvel, float yvel) {
      }
    });
  }

  @Override
  public boolean onInterceptTouchEvent(MotionEvent event){
    return viewDragHelper.shouldInterceptTouchEvent(event);
  }

  @Override
  public boolean onTouchEvent(MotionEvent event) {
    viewDragHelper.processTouchEvent(event);
    return true;
  }
}

第三步,将拼图Bitmap按九宫格切割,生成ImageView添加到PuzzleLayout并进行排列。

首先,外界需要传入一个切割参数mSquareRootNum做为宽和高的切割份数,我们需要获取PuzzleLayout的宽和高,然后计算出每一块的宽mItemWidth和高mItemHeight, 将Bitmap等比例缩放到和PuzzleLayout大小相等,然后将图片按照类似上面这张图所标的形式进行切割,生成mSquareRootNum*mSquareRootNum份Bitmap,每个Bitmap对应创建一个ImageView载体添加到PuzzleLayout中,并进行布局排列。

创建子view, mHelper是封装的用来操作对应数据模型的帮助类DataHelper。

/**
 * 将子View index与mHelper中models的index一一对应,
 * 每次在交换子View位置的时候model同步更新currentPosition。
 */
private void createChildren(){
  mHelper.setSquareRootNum(mSquareRootNum);

  DisplayMetrics dm = getResources().getDisplayMetrics();
  BitmapFactory.Options options = new BitmapFactory.Options();
  options.inDensity = dm.densityDpi;

  Bitmap resource = BitmapFactory.decodeResource(getResources(), mDrawableId, options);
  Bitmap bitmap = BitmapUtil.zoomImg(resource, mWidth, mHeight);
  resource.recycle();

  mItemWidth = mWidth / mSquareRootNum;
  mItemHeight = mHeight / mSquareRootNum;

  for (int i = 0; i < mSquareRootNum; i++){
    for (int j = 0; j < mSquareRootNum; j++){
      Log.d(TAG, "mItemWidth * x " + (mItemWidth * i));
      Log.d(TAG, "mItemWidth * y " + (mItemWidth * j));
      ImageView iv = new ImageView(getContext());
      iv.setScaleType(ImageView.ScaleType.FIT_XY);
      LayoutParams lp = new LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
      lp.leftMargin = j * mItemWidth;
      lp.topMargin = i * mItemHeight;
      iv.setLayoutParams(lp);
      Bitmap b = Bitmap.createBitmap(bitmap, lp.leftMargin, lp.topMargin, mItemWidth, mItemHeight);
      iv.setImageBitmap(b);
      addView(iv);
    }
  }
}

第四步,创建ImageView的对应数据模型。

public class Block {
  public Block(int position, int vPosition, int hPosition){
    this.position = position;
    this.vPosition = vPosition;
    this.hPosition = hPosition;
  }
  public int position;
  public int vPosition;
  public int hPosition;
}

DataHelper.class

子View在父类的index与mHelper中model在models的index一一对应

class DataHelper {
  static final int N = -1;
  static final int L = 0;
  static final int T = 1;
  static final int R = 2;
  static final int B = 3;
  private static final String TAG = DataHelper.class.getSimpleName();

  private int squareRootNum;
  private List<Block> models;

  DataHelper(){
    models = new ArrayList<>();
  }

  private void reset() {
    models.clear();
    int position = 0;
    for (int i = 0; i< squareRootNum; i++){
      for (int j = 0; j < squareRootNum; j++){
        models.add(new Block(position, i, j));
        position ++;
      }
    }
  }

  void setSquareRootNum(int squareRootNum){
    this.squareRootNum = squareRootNum;
    reset();
  }
}

第五步,ViewDragHelper.Callback控制滑动边界的实现。

tryCaptureView的实现

public boolean tryCaptureView(View child, int pointerId) {
      int index = indexOfChild(child);
      return mHelper.getScrollDirection(index) != DataHelper.N;
    }

DataHelper的getScrollDirection函数

/**
 * 获取索引处model的可移动方向,不能移动返回 -1。
 */
int getScrollDirection(int index){

  Block model = models.get(index);
  int position = model.position;

  //获取当前view所在位置的坐标 x y
  /*
   *   * * * *
   *   * o * *
   *   * * * *
   *   * * * *
   */
  int x = position % squareRootNum;
  int y = position / squareRootNum;
  int invisibleModelPosition = models.get(0).position;

  /*
   * 判断当前位置是否可以移动,如果可以移动就return可移动的方向。
   */

  if(x != 0 && invisibleModelPosition == position - 1)
    return L;

  if(x != squareRootNum - 1 && invisibleModelPosition == position + 1)
    return R;

  if(y != 0 && invisibleModelPosition == position - squareRootNum)
    return T;

  if(y != squareRootNum - 1 && invisibleModelPosition == position + squareRootNum)
    return B;

  return N;
}

clampViewPositionHorizontal的实现细节,获取滑动方向左或右,再控制对应的滑动区域。

public int clampViewPositionHorizontal(View child, int left, int dx) {

      int index = indexOfChild(child);
      int position = mHelper.getModel(index).position;
      int selfLeft = (position % mSquareRootNum) * mItemWidth;
      int leftEdge = selfLeft - mItemWidth;
      int rightEdge = selfLeft + mItemWidth;
      int direction = mHelper.getScrollDirection(index);
      //Log.d(TAG, "left " + left + " index" + index + " dx " + dx + " direction " + direction);
      switch (direction){
        case DataHelper.L:
          if(left <= leftEdge)
            return leftEdge;
          else if(left >= selfLeft)
            return selfLeft;
          else
            return left;

        case DataHelper.R:
          if(left >= rightEdge)
            return rightEdge;
          else if (left <= selfLeft)
            return selfLeft;
          else
            return left;
        default:
          return selfLeft;
      }
    }

clampViewPositionVertical的实现细节,获取滑动方向上或下,再控制对应的滑动区域。

public int clampViewPositionVertical(View child, int top, int dy) {
      int index = indexOfChild(child);
      Block model = mHelper.getModel(index);
      int position = model.position;

      int selfTop = (position / mSquareRootNum) * mItemHeight;
      int topEdge = selfTop - mItemHeight;
      int bottomEdge = selfTop + mItemHeight;
      int direction = mHelper.getScrollDirection(index);
      //Log.d(TAG, "top " + top + " index " + index + " direction " + direction);
      switch (direction){
        case DataHelper.T:
          if(top <= topEdge)
            return topEdge;
          else if (top >= selfTop)
            return selfTop;
          else
            return top;
        case DataHelper.B:
          if(top >= bottomEdge)
            return bottomEdge;
          else if (top <= selfTop)
            return selfTop;
          else
            return top;
        default:
          return selfTop;
      }
    }

onViewReleased的实现,当松手时,不可见View和松开的View之间进行布局参数交换,同时对应的model之间也需要通过swapValueWithInvisibleModel函数进行数据交换。

public void onViewReleased(View releasedChild, float xvel, float yvel) {
      Log.d(TAG, "xvel " + xvel + " yvel " + yvel);
      int index = indexOfChild(releasedChild);
      boolean isCompleted = mHelper.swapValueWithInvisibleModel(index);
      Block item = mHelper.getModel(index);
      viewDragHelper.settleCapturedViewAt(item.hPosition * mItemWidth, item.vPosition * mItemHeight);
      View invisibleView = getChildAt(0);
      ViewGroup.LayoutParams layoutParams = invisibleView.getLayoutParams();
      invisibleView.setLayoutParams(releasedChild.getLayoutParams());
      releasedChild.setLayoutParams(layoutParams);
      invalidate();
      if(isCompleted){
        invisibleView.setVisibility(VISIBLE);
        mOnCompleteCallback.onComplete();
      }
    }

viewDragHelper.settleCapturedViewAt和viewDragHelper.continueSettling配合实现松手后的动画效果。

PuzzleLayout重写computeScroll函数。

@Override
public void computeScroll() {
  if(viewDragHelper.continueSettling(true)) {
    invalidate();
  }
}

swapValueWithInvisibleModel函数,每次交换完成后会return拼图是否完成


/**
 * 将索引出的model的值与不可见
 * model的值互换。
 */
boolean swapValueWithInvisibleModel(int index){
  Block formModel = models.get(index);
  Block invisibleModel = models.get(0);
  swapValue(formModel, invisibleModel);
  return isCompleted();
}

/**
 * 交换两个model的值
 */
private void swapValue(Block formModel, Block invisibleModel) {

  int position = formModel.position;
  int hPosition = formModel.hPosition;
  int vPosition = formModel.vPosition;

  formModel.position = invisibleModel.position;
  formModel.hPosition = invisibleModel.hPosition;
  formModel.vPosition = invisibleModel.vPosition;

  invisibleModel.position = position;
  invisibleModel.hPosition = hPosition;
  invisibleModel.vPosition = vPosition;
}

/**
 * 判断是否拼图完成。
 */
private boolean isCompleted(){
  int num = squareRootNum * squareRootNum;
  for (int i = 0; i < num; i++){
    Block model = models.get(i);
    if(model.position != i){
      return false;
    }
  }
  return true;
}

第六步,打乱ImageView的摆放位置。

这里不能随意打乱顺序,否则你可能永远也不能复原拼图了,这里使用的办法是每次在不可见View附近随机找一个View与不可见View进行位置交换,这里的位置交换指的是布局参数的交换,同时对应的数据模型也需要进行数据交换。

public void randomOrder(){
  int num = mSquareRootNum * mSquareRootNum * 8;
  View invisibleView = getChildAt(0);
  View neighbor;
  for (int i = 0; i < num; i ++){
    int neighborPosition = mHelper.findNeighborIndexOfInvisibleModel();
    ViewGroup.LayoutParams invisibleLp = invisibleView.getLayoutParams();
    neighbor = getChildAt(neighborPosition);
    invisibleView.setLayoutParams(neighbor.getLayoutParams());
    neighbor.setLayoutParams(invisibleLp);
    mHelper.swapValueWithInvisibleModel(neighborPosition);
  }
  invisibleView.setVisibility(INVISIBLE);
}

DataHelper中findNeighborIndexOfInvisibleModel函数

/**
 * 随机查询出不可见
 * 位置周围的一个model的索引。
 */
public int findNeighborIndexOfInvisibleModel() {
  Block invisibleModel = models.get(0);
  int position = invisibleModel.position;
  int x = position % squareRootNum;
  int y = position / squareRootNum;
  int direction = new Random(System.nanoTime()).nextInt(4);
  Log.d(TAG, "direction " + direction);
  switch (direction){
    case L:
      if(x != 0)
        return getIndexByCurrentPosition(position - 1);
    case T:
      if(y != 0)
        return getIndexByCurrentPosition(position - squareRootNum);
    case R:
      if(x != squareRootNum - 1)
        return getIndexByCurrentPosition(position + 1);
    case B:
      if(y != squareRootNum - 1)
        return getIndexByCurrentPosition(position + squareRootNum);
  }
  return findNeighborIndexOfInvisibleModel();
}

/**
 * 通过给定的位置获取model的索引
 */
private int getIndexByCurrentPosition(int currentPosition){
  int num = squareRootNum * squareRootNum;
  for (int i = 0; i < num; i++) {
    if(models.get(i).position == currentPosition)
      return i;
  }
  return -1;
}

以上为主要的代码实现,全部工程已上传Github,欢迎学习,欢迎star,传送门
https://github.com/kevin-mob/Puzzle

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

(0)

相关推荐

  • Android ViewDragHelper仿淘宝拖动加载效果

    拖动加载是我在淘宝的商品详情界面发现的,感觉很实用.于是就分析它的实现方式,感觉用ViewDragHelper可以很方便的实现这种效果.下面大致把我的思路分步骤写一下.先上图吧. 首先建工程什么的我就不多说了.咱从ViewDragHelper的实现开始说吧,ViewDragHelper一般用在一个自定义ViewGroup的内部,可以对其子View进行移动操作. 创建自定义ViewGroup: package com.maxi.viewdraghelpertest.widget; import a

  • Android ViewDragHelper使用介绍

    ViewDragHelper是support.v4下提供的用于处理拖拽滑动的辅助类,查看Android的DrawerLayout源码,可以发现,它内部就是使用了该辅助类来处理滑动事件的. public DrawerLayout(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); setDescendantFocusability(ViewGroup.FOCUS_AFTER_DE

  • Android使用ViewDragHelper实现仿QQ6.0侧滑界面(一)

    QQ是大家离不开的聊天工具,方便既实用,自从qq更新至6.0之后,侧滑由原来的划出后主面板缩小变成了左右平滑,在外观上有了很大的提升,于是我就是尝试理解下里面的各种逻辑,结合相关资料,研究研究. 知道这里面的一个主要类是ViewDragHelper,那么首先我们要先来了解一下这个ViewDragHelper类,正所谓打蛇打七寸,我们就先来看看官方文档怎么介绍的,有什么奇特的功能. 首先继承: java.lang.Object android.support.v4.widget.ViewDragH

  • Android基于ViewDragHelper仿QQ5.0侧滑界面效果

    QQ5.0侧滑效果实现方案有很多方式,今天我们使用ViewDragHelper来实现一下. 先上效果图: ①自定义控件SlidingMenu继承FrameLayout,放在FrameLayout上面的布局一层叠着者一层,通过getChildAt()可以很方便的获取到任意一层,进而控制此布局的变化. public class SlidingMenu extends FrameLayout { private ViewDragHelper mViewDragHelper; private int m

  • Android ViewDragHelper完全解析 自定义ViewGroup神器

    一.概述 在自定义ViewGroup中,很多效果都包含用户手指去拖动其内部的某个View(eg:侧滑菜单等),针对具体的需要去写好onInterceptTouchEvent和onTouchEvent这两个方法是一件很不容易的事,需要自己去处理:多手指的处理.加速度检测等等. 好在官方在v4的支持包中提供了ViewDragHelper这样一个类来帮助我们方便的编写自定义ViewGroup.简单看一下它的注释: ViewDragHelper is a utility class for writin

  • Android使用ViewDragHelper实现QQ6.X最新版本侧滑界面效果实例代码

    (一).前言: 这两天QQ进行了重大更新(6.X)尤其在UI风格上面由之前的蓝色换成了白色居多了,侧滑效果也发生了一些变化,那我们今天来模仿实现一个QQ6.X版本的侧滑界面效果.今天我们还是采用神器ViewDragHelper来实现. 本次实例具体代码已经上传到下面的项目中,欢迎各位去star和fork一下. https://github.com/jiangqqlmj/DragHelper4QQ FastDev4Android框架项目地址:https://github.com/jiangqqlm

  • Android 中通过ViewDragHelper实现ListView的Item的侧拉划出效果

    先来看看,今天要实现的自定义控件效果图: 关于ViewDragHelper的使用,大家可以先看这篇文章ViewDragHelper的使用介绍 实现该自定义控件的大体步骤如下: 1.ViewDragHelper使用的3部曲,初始化ViewDragHelper,传递触摸事件,实现ViewDragHelper.Callback抽象类. 2.需要创建2个直接的子View,分别是前景View和背景View,代表ListView每一项Item的布局的组成,如下所示: 未划出时显示的FrontView: 划出

  • Android利用ViewDragHelper轻松实现拼图游戏的示例

    前言 最近一段时间看了一些介绍ViewDragHelper的博客,感觉这是一个处理手势滑动的神奇,看完以后就想做点东西练练手,于是就做了这个Android拼图小游戏. 先上个效果图 源码 https://github.com/kevin-mob/Puzzle ViewDragHelper 其实ViewDragHelper并不是第一个用于分析手势处理的类,gesturedetector也是,但是在和拖动相关的手势分析方面gesturedetector只能说是勉为其难. 关于ViewDragHelp

  • Android 利用三阶贝塞尔曲线绘制运动轨迹的示例

    本篇文章主要介绍了Android 利用三阶贝塞尔曲线绘制运动轨迹的示例,分享给大家,具体如下: 实现点赞效果,自定义起始点以及运动轨迹 效果图: xml布局: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/rl_root&

  • 利用Matlab制作三子棋游戏的示例代码

    效果: 注: 由于用uifigure和uiaxes写的会比较慢,改成常规的axes和figure会快很多. 完整代码: function OX_chess fig=uifigure('units','pixels',... 'position',[350 100 500 500],... 'Numbertitle','off',... 'name','OX_chess',... 'Color',[1 1 1],... 'resize','off',... 'menubar','none'); a

  • Android利用FlexboxLayout轻松实现流动布局

    前言 相信大家应该都有所体会,在以前我们要实现流动性布局,比较繁琐,Google开源了一个项目叫FlexboxLayout,相信大家都不陌生.下面我们来学习一下FlexboxLayout基础知识,并通过一个案例来加深理解.如果你对FlexboxLayout很熟悉,请忽略本文. 一.什么是 Flexbox 简单来说 Flexbox 是属于web前端领域CSS的一种布局方案,是2009年W3C提出了一种新的布局方案,可以响应式地实现各种页面布局,并且 React Native 也是使用的 Flex

  • Android使用ViewDragHelper实现图片下拽返回示例

    微信的图片下拽返回功能在日常使用中非常方便,同时在很多 App 中都见到了类似的设计,可以说一旦习惯这种操作再也回不去了. 这几天逛 GitHub,发现一个很赞的库 https://github.com/iielse/ImageWatcher高度还原了微信的效果,粗看了下源码,我觉得可以更简单的实现类似的效果,动手实现后,发现 ViewDragHelper + ActvitySceneTransition 的方案简单粗暴,废话不说,先看效果: 什么是 ViewDragHelper 具体实现之前先

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

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

  • Android实现九宫格拼图游戏

    经常有同学问到,使用Android能不能开发游戏呢?能开发那些游戏呢?由于操作系统和开发语言局限,一般开发安卓手机游戏,我们很少使用其自带语言开发.而是使用指定编译器和语言完成,能够使界面更流畅,用户体验感更好.但是对于一些常见小游戏,使用JAVA语言开发运行,还是不在话下的,那在本篇博客中,我将给大家简单介绍一下,九宫格拼图游戏的开发过程,基本逻辑和思路我将在代码的注释中体现. 九宫格拼图游戏,相信大家小时候都玩过.大概逻辑是,将1张图采用3*3的方式,分成9部分,将第3行3列的小图取出,打乱

  • android实现简单拼图游戏

    本文实例为大家分享了android实现简单拼图游戏的具体代码,供大家参考,具体内容如下 1. 2. //使用回调接口,首先初始化pintuview并绑定,实现回调接口的方法     mPintuLayout = (PintuLayout) findViewById(R.id.mpintu);         mPintuLayout.setOnGamePintuListener(new GamePintuListener() {             @Override            

  • 利用adt-bundle轻松搭建Android开发环境与Hello world(Linux)

    本文与<利用adt-bundle轻松搭建Android开发环境与Hello world(Windows) >是姊妹篇,只是这次操作换成了Linux .拿Ubuntu做例子.还是与Windows一样.由于JDK+Eclipse+ADT+SDK或者JDK+Android Studio在安装的过程中非得联网不可.因此也选用了JDK1.7+解压即用的官方绿色版Android开发环境adt-bundle20131030去安装. 一.基本准备 首先还是与<Debian配置JDK1.7 与Linux

  • Android版微信跳一跳小游戏利用技术手段达到高分的操作方法

    本文主要来讲个个好玩的东西,近来微信刚出的跳一跳微信小程序的游戏很火,看到很多人都达到了二三百分就各种刷朋友圈了. 甩手一个表情 最终我们达到的分数却是这样的: 羡慕吧 一定会有人拍手叫好,"黄金右手"!说真的,我已经不用右手好多年,而且我玩这个游戏压根就没用手,而是意念!哈哈,别喷我,开个玩笑而已,肯定是利用技术手段啦,什么技术?python喽-哈哈,不过不是我写的,我自己是做Android开发的,我对于python从来没有接触,只是恰好在蛋哥公众号看到关于这个游戏的文章,觉得有意思

随机推荐