人机交互实验:Android开发之人物移动、地图滑动、传感器、触屏的应用
来源:互联网 发布:淘宝网怎么增加流量 编辑:程序博客网 时间:2024/06/05 14:24
Android开发,人物移动与地图滑动,传感器、触屏的应用
1.程序介绍
这是我们人机交互课的实验,老师对我们的要求如下:
- 1.能绘制出二维卷轴地图,及人物可在地图上各方向移动
- 2.在第1次的基础上加入交互,用手指控制人物的移动和地图的缩放等,实现一指交互、二指交互。
- 3.在之前的基础上,实现使用手机上2种感应器在程序中的作用,例如重力感应器、GPS、加速度感应器等
先给个程序的截图吧~
2.人物移动和地图滑动
参考该博客Android游戏开发之主角的移动和地图的平滑滚动
我程序的框架是参考该博客中的程序,它已经实现了地图的绘制、用键盘控制人物的移动,所以其它的功能我是在该程序的基础上实现的。
其余的不说了,先说说原来程序的不足之处
2.1 源程序引用数值较多
这是我很不喜欢源程序的地方,因为很多地方用的直接是数值,一方面很难让人知道该数值的含义,另一方面也使得若换不同的地图、不同屏幕像素的手机等,得重新改动,比如UpdateHero方法中,如何判断接下来是人物移动还是地图滑动,在if中用了很多数值,一开始看的话,你根本不知道这些数值代表什么!
在我的程序中,我多定义了些变量,由变量算出这些数值,这样换地图的话只要更改地图的宽高,换手机的话就什么都不用改。给出前后代码的对比。
//原来的人物往下移动的处理if (mHeroScreenY >= 320) { if (mHeroIndexY >= 10 && mHeroIndexY <= 20) { mMapPosY -= HERO_STEP; } else { mHeroScreenY += HERO_STEP; }} else { mHeroScreenY += HERO_STEP;}/* * 我对人物往下移动的处理 * 先对代码做一些解释,当然,数值是来源于原来代码中的。 * 地图上下移动有个范围,地图上界即屏幕上界~地图下界即屏幕下界 * 地图最上端为屏幕最上端时,320/32=10 * 地图最下端为屏幕最下端时,(800-160)/32=20 * 但若<=20,则地图最下面会有一小部分重复往上动,走到那里会出现多个人 改成17后,就没事了。 * 这是因为有的手机像素高度比较大(大于800),所以会出现最下面地图重复移动的情况 */if (mHeroScreenY >= h * 2) { if (mHeroIndexY >= h * 2 / 32 && mHeroIndexY <= (SCENCE_HEIGHT - h) / 32) { //mMapPosY:地图的坐标,即人物不动,地图往上移动,也就是地图的Y坐标减小 mMapPosY -= HERO_STEP; } else { mHeroScreenY += HERO_STEP; }} else { // 人就在屏幕上往下移动 mHeroScreenY += HERO_STEP;}
2.2 源程序对碰撞处理不是很好
我参考的源程序对碰撞进行了处理,但是处理考虑不全面!在控制人物移动过程中,刚开始,嗯,不错,碰撞处理挺好的。可是当你人物继续移动,直到人物在屏幕上位置不变,而地图开始移动的时候,这是若碰到物体,你会发现竟然穿过去了!!!我通过用Log.v()方法输出想要的内容,调试了好久,终于被我发现了错误。
先看看对碰撞的处理:
if (mCollision[mHeroIndexY][mHeroIndexX] == -1) { mHeroPosX = mBackHeroPosX; mHeroPosY = mBackHeroPosY; mHeroScreenY = mBackHeroScreenY; mHeroScreenX = mBackHeroScreenX; //下面是我增加的 mMapPosX = mBackmMapPosX; mMapPosY = mBackmMapPosY; isAcotrCollision = true;} else { mBackHeroPosX = mHeroPosX; mBackHeroPosY = mHeroPosY; mBackHeroScreenX = mHeroScreenX; mBackHeroScreenY = mHeroScreenY; //下面是我增加的 mBackmMapPosX = mMapPosX; mBackmMapPosY = mMapPosY; isAcotrCollision = false;}
若发生碰撞,人物在屏幕、地图中的x、y坐标进行回退,即回退到前一次的。细心的童鞋可以发现,它还缺少了一种可能。那就是当人物过了屏幕宽或高的三分之二,实际上是地图在滑动了。针对该种情形下发生碰撞,源代码中并没对地图的x,y坐标进行回退!所以导致地图在滑动的时候,即使发生碰撞,地图还在滑动,这就导致人物穿墙的问题!
3.触屏控制
3.1 一指触屏控制人物移动
原先是通过键盘控制的,若要增加触屏控制人物移动,其实很好办,因为原先的代码都已经把框架给写好了,原文中通过下面四个变量,来判断人物是往哪里移动。
/** 按键下 **/ private boolean mIskeyDown = false; /** 按键左 **/ private boolean mIskeyLeft = false; /** 按键右 **/ private boolean mIskeyRight = false; /** 按键上 **/ private boolean mIskeyUp = false;
所以在触屏的代码中,我们只要根据手指不同的位置,通过原来代码中的下面方法:
public void setKeyState(int keyCode, boolean state) { switch (keyCode) { case KeyEvent.KEYCODE_DPAD_DOWN: mIskeyDown = state; break; case KeyEvent.KEYCODE_DPAD_UP: mIskeyUp = state; break; case KeyEvent.KEYCODE_DPAD_LEFT: mIskeyLeft = state; break; case KeyEvent.KEYCODE_DPAD_RIGHT: mIskeyRight = state; break; } mAllkeyDown = state;}
用setKeyState()将对应方向的布尔变量设置为true,人自然而然就会往对应方向移动了。
一指触控的代码是实现了onTouchEvent()方法,该方法属于Activity,所以凡是继承了Activity的类,都可以覆盖该方法。
关于该方法,可以见Android开发教程: 触摸屏模拟实现方向键
怎么控制人物移动呢,我是通过获取手指的x,y坐标与人物在屏幕中的x,y坐标的差的绝对值,哪个大就在哪个方向上移动。具体见代码:
public boolean onTouchEvent(MotionEvent event) { //这是两指触控实现缩放的,在这里先注释掉 //if (event.getPointerCount() == 2) { // setMultiTouch(event); //} float x = event.getX(); float y = event.getY(); float dx, dy; float mX = mAnimView.mHeroScreenX, mY = mAnimView.mHeroScreenY; switch (event.getAction()) { // 触摸结束 case MotionEvent.ACTION_UP: isFirst = true; oldRate = rate; // 手指离开屏幕,则人物不动,下面是我增加的方法,使所有方向都为false mAnimView.setKeyStateFalse(); return false; case MotionEvent.ACTION_DOWN: // mAnimView.setKeyStateFalse(); dx = x - mX; dy = y - mY; int i,j; float adx=Math.abs(dx); float ady=Math.abs(dy); if (adx >= ady) { // move from left -> right //这里为什么>35,是因为我还要用<35的那些范围用于其它的功能实现。 //后面的48,也是同样道理。 if (dx > 35.0f) { mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_RIGHT, true); } else if (dx<-35.0f){ mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_LEFT, true); } } else { // move from top -> bottom or bottom -> top if (dy > 48.0f) { mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_DOWN, true); } else if(dy<-48.0f){ mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_UP, true); } } return true; /** * MOVE是介于MotionEvent.ACTION_DOWN和MotionEvent.ACTION_UP之间的, * 所以通过MOVE来控制人物移动 如果用MotionEvent.ACTION_DOWN的话, * 则至少在我的手机上,只能每次按一下走一步,太不方便了 */ case MotionEvent.ACTION_MOVE: dx = x - mX; dy = y - mY; if (Math.abs(dx) >= Math.abs(dy)) { // move from left -> right // or right -> left if (dx > 0.0f) { mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_RIGHT, true); } else { mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_LEFT, true); } } else { // move from top -> bottom or bottom -> top if (dy > 0.0f) { mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_DOWN, true); } else { mAnimView.setKeyState(KeyEvent.KEYCODE_DPAD_UP, true); } } return true; } return super.onTouchEvent(event);}
3.2 二指实现地图缩放
《Android游戏编程之从零开始》里面有讲到,参考这个链接吧多触点实现图片缩放。我是通过上面中注释掉的setMultiTouch(event)方法来实现地图缩放的,详情的话就参加我的代码,本文最后会给出下载链接。 这里遇到一个问题,那就是当地图不断缩小时,屏幕上剩余部分会残留之前刷新的图片,所以每次缩小之前,得先清屏一下。android开发--Canvas清屏只需三句话
if (isShrink) { Paint p = new Paint(); p.setXfermode(new PorterDuffXfermode(Mode.CLEAR)); mCanvas.drawPaint(p); p.setXfermode(new PorterDuffXfermode(Mode.SRC));}//接下来可以通过mCanvas.drawColor(Color.WHITE)来改变背景颜色
4. 传感器的应用
4.1 加速度感应器的应用
我通过加速度感应器,实现了两个功能:1.控制人物移动,2.通过摇一摇换人物主角(牧场物语矿石镇的伙伴男女主人公)
参考下面两个文章:
Android游戏开发之小球重力感应实现
Android之摇一摇功能
4.2 光线传感器的使用
没办法, 老师要求要用两个传感器,可是发现可以用的传感器除了加速度感应,其它的实在没什么。。。所以勉强用了个光线传感器,若光线暗的话,就把背景从白色亮的变为灰色(保护眼睛)。。。真的是为了用而用。。。
两个传感器实现代码如下:
/*传感器相关变量 *private SensorManager mSensorMgr = null; *Sensor mSensor = null; *Sensor mSensor2 = null; *mSensorMgr = (SensorManager) getSystemService(SENSOR_SERVICE); *mSensor = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); *mSensor2 = mSensorMgr.getDefaultSensor(Sensor.TYPE_LIGHT); *mSensorMgr.registerListener(this, mSensor,SensorManager.SENSOR_DELAY_GAME); *mSensorMgr.registerListener(this, mSensor2,SensorManager。SENSOR_DELAY_GAME); */public void onSensorChanged(SensorEvent event) { // 加速度传感器 if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { mGX = event.values[0]; mGY = event.values[1]; mGZ = event.values[2]; setKeyStateFalse(); if (Math.abs(mGX) >= Math.abs(mGY) && Math.abs(mGX) >= 1.0) { if (mGX >= 0) { // 向左走 setKeyState(KeyEvent.KEYCODE_DPAD_LEFT, true); } else { // 向右走 setKeyState(KeyEvent.KEYCODE_DPAD_RIGHT, true); } } else if (Math.abs(mGX) < Math.abs(mGY) && Math.abs(mGY) >= 1.0) { // 这里之所以设置成一个大于6.0,一个小于3.0,是因为人拿手机的时候,手机基本上就是倾斜的,mGY肯定大于0. if (1.0 <mGY && mGY< 4.0) // 向上走 setKeyState(KeyEvent.KEYCODE_DPAD_UP, true); else if (mGY >= 7.0) { // 向下走 setKeyState(KeyEvent.KEYCODE_DPAD_DOWN, true); } } //摇一摇换主角 int minValue=19; if (Math.abs(mGX) > minValue || Math.abs(mGY) > minValue || Math.abs(mGZ) > minValue) { roleId=(roleId+1)%2; } } //光线传感器 else if(event.sensor.getType() == Sensor.TYPE_LIGHT){ float lv=event.values[0]; if(lv>10.0f){ isNight=false; } else{ isNight=true; } }}
5.增加种植、收割功能
之前在3.1触屏控制人物移动的代码中提到,选取abs|dx|>35或者abs|dy|>48,才允许人物朝相应的方向移动。之所以留出人物周围一部分的范围,是用于种植一些农产品。就是当人物在农田中时,手指触摸人物一小部分范围内,可以种上东西。对种上东西的地方再触摸一次,就收割农产品。(说简单点,其实就是画上一个图片、消除一个图片。。。)
给个图:
这里用到了mMapAcotor数组,若值为-1,表示没有什么。若为0~5,对应6种不同的农产品。根据不同的索引值,在地图位置画上对应农产品的位图。在OnTouchEvent方法中增加的部分代码:
if(adx<=32.0f){ //先算出手指触摸的地方在地图中对应的数组索引 i=(-mAnimView.mMapPosX+(int)x)/mAnimView.TILE_WIDTH; j=(-mAnimView.mMapPosY+(int)y)/mAnimView.TILE_HEIGHT; if(mAnimView.mMapAcotor[j][i]==-1){ //随机一个农产品 int tmp=rand.nextInt(mAnimView.totOfProds); mAnimView.mMapAcotor[j][i]=tmp; //mAnimView.numOfProds[tmp]++; } else{ mAnimView.isHarvest=true; //起不了作用,屏幕没有显示收割。。。 //mAnimView.numOfProds[mAnimView.mMapAcotor[j][i]]--; mAnimView.mMapAcotor[j][i]=-1; }}
6. 增加背景音乐设置
详细就见代码,不说了,给个截图吧
7. 源代码下载
- 人机交互实验:Android开发之人物移动、地图滑动、传感器、触屏的应用
- 游戏开发之--简单的人物走动和地图移动(一)
- Android开发 百度地图开发(定位、传感器应用)
- Android实现人物在地图中移动
- Android 传感器应用开发
- Android传感器应用开发
- 移动开发人机交互
- Android平台下传感器应用的开发
- Android 之 传感器 应用
- Android开发传感器应用---获取方向传感器
- Android开发之传感器
- Android开发之方向传感器的使用
- Android开发之方向传感器的使用
- Android开发之方向传感器的使用
- Android开发之方向传感器的…
- Android开发之方向传感器的使用
- Android的传感器应用
- Android传感器的应用
- 微信调试、手机QQ调试、Qzone之x5内核inspect调试解决方案
- 我真的喜欢现在做的事情,现在的生活吗?
- C语言编程基础-12指针
- Caused by: android.view.WindowManager$BadTokenException: Unable to add window -
- C语言编程基础-13字符串操作与指针数组
- 人机交互实验:Android开发之人物移动、地图滑动、传感器、触屏的应用
- app接入支付宝接口
- 2012年5月SAT香港真题解析
- Android Activity之---(生命周期)
- C语言编程基础-14文件位置指针 宏操作 多文件编程
- SpringMVC介绍之视图解析器ViewResolver
- 【UIKit】-10-UIAlertView - iOS 8 之后弃用,改用 UIAlertViewController
- C语言编程基础-15结构体 枚举 联合
- GRE写作必备句型