先看运行效果:(截图还是失真)
代码结构很乱,主要描述下思路与在这个过程中的收获,希望之后可以借鉴~
SurfaceView
首先了解下surfaceView /View
这两者最大的区别是前者是另开一个新的线程去画图,多用于游戏画面主动更新的,以防止阻塞UI线程,而View是在UI线程更新,用于画面被动更新。
这里用的是surfaceView,surface是surfaceView中的一个可见部分,可以理解成一块内存区域,然后系统根据内存中的内容通过显示设备输出,这一块内存区域的管理者就是surfaceHolder,他将surface的创建,改变,销毁交给了Callback,下面是使用surfaceView的一个框架
public class mapView extends SurfaceView implements SurfaceHolder.Callback,Runnable{
SurfaceHolder mHolder ;
Thread thread;
boolean isRun;
public mapView(Context context, int width,int height) {
super(context);
mHolder = this.getHolder();
mHolder.addCallback(this);
thread = new Thread(this);
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
isRun = true;
thread.start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
isRun = false;
}
/*
* 绘图线程
* (non-Javadoc)
* @see java.lang.Runnable#run()
*/
@Override
public void run() {
// TODO Auto-generated method stub
while(isRun){
synchronized(mHolder){
mCanvas = mHolder.lockCanvas();
}
mHolder.unlockCanvasAndPost(mCanvas);
}
}
}
描述下surfaceView的使用过程:
1.首先需要继承surfaceView类,然后实现SurfaceHolder.Callback和Runnable接口
2.在构造函数中实例化holder并用holder添加callback,同时实例化用于专门画图的线程
3.在surfaceCreated中启动线程
4.实现Runnable的run方法,holder.lockCanvas与holder.unlockCanvas
构建地图
知道上述这些,就已经成功了一半,然后我们先来看地图的画法
这是在网上找到的一张图,分辨率是1024*768 每块64x64,宽16高12(需要考虑图中道路的块大小),推荐使用mapwin
首先画地图,很简单
for(i=0;i<mMapWpiece;i++){
for(j=0;j<mMapHpiece;j++){
src.left =mPieceW*i;
src.top = mPieceH*j;
src.right = mPieceW*(i+1);
src.bottom = mPieceH*(j+1);
dst.left =mScrWpiece*i;
dst.top = mScrHpiece*j;
dst.right = mScrWpiece*(i+1);
dst.bottom = mScrHpiece*(j+1);
mCanvas.drawBitmap(mBitmap, src, dst, mPaint);
}
}
当然还要有一个数组标识有效区,碰撞区,无效区
int[][] mMaparray = {
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{-1,-1,-1,-1,-1, 0, 0, 0,-1,-1,-1,-1,-1,-1,-1,-1},
{ 1, 1, 1, 1,-1, 0, 0, 0,-1, 1, 1, 1, 1, 1, 1, 1},
{-1,-1,-1, 1,-1, 0, 0, 0,-1, 1,-1,-1,-1,-1,-1,-1},
{ 0, 0,-1, 1,-1, 0, 0, 0,-1, 1,-1, 0, 0, 0, 0, 0},
{ 0, 0,-1, 1,-1,-1,-1,-1,-1, 1,-1, 0, 0, 0, 0, 0},
{ 0, 0,-1, 1, 1, 1, 1, 1, 1, 1,-1, 0, 0, 0, 0, 0},
{ 0, 0,-1,-1,-1,-1,-1,-1,-1,-1,-1, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
很明显图中的的1构成了一条有效的道路,道路周围都是碰撞去,0为无效区
帧动画
帧动画就是将很多图片以一定的速度加载,给人动画的错觉,下图是一张制作动画的素材
首先我们先实现第一行三帧的动画,方法很简单,比如在(0,0)处让小人一直走动
1.在(0,0)出画第一帧,等待200毫秒
2.画第二帧,等待200毫秒
...
其中第一帧、第二帧、第三帧的获取是通过控制drawBitmap参数中的Rect src来控制的,其他的就是通过一些循环、位置的控制来实现(最还自己想,看别人的反而慢...)
走起来
这一步,就是把人物和地图联系起来,根据地图的数组的值,判断人物下一步的方向与位置,然后由上面的的(0,0)变化到(1,0)....(240,320)...
Ps:代码实在是乱,自己都看不下去了,之后重构下再贴吧.