M8下开发重力感应程序

转载请注明出处

作者:小马

 

M8支持重力感应, 本人研究了一把m8的重力感应, 写点小经验.

 

1 物理知识

重力感应的原理是利用重力加速度,而重力加速度是加速度的一种, 比如一辆汽车在水平的路面上加速行驶, 它在水平方向是有一个加速度的, 而竖直方向的加速度为0(虽然受到重力加速度,但是被抵消了),重力加速度是个常量(在某固定一地点),通常取9.8. 这个加速度是由地球重力产生的。一个自由落体的物体(理论环境),它的加速度为9.8.等于重力常量, 而在斜坡上下落的物体(假如不考虑摩擦力, 在手机应用中也是如此),它的加速度要小于9.8(只是9.8的一个分量).基于重力感应的应用程序,往往都需要计算物体在某一时刻的位移, 由加速度计算位移很简单,有公式,时间也容易得到.

 

M8的sdk里有获取各个坐标(x,y,z)的重力加速度分量的API, 有了这些函数,就可以开发出各种相关的应用了.要注意重力加速度坐标是以手机本身为参考点的,理解这一点很重要, 拿m8举个例子, 把手机平放在桌面上, 它的重力加速度坐标系如下:

M8下开发重力感应程序_第1张图片


Z轴倒没问题, x轴和y轴的坐标倒是让人想不明白, 跟窗口坐标系刚好反过来, 很容易造成误解,想不明白mz这样设计是基于什么考虑的.


2 硬件原理

iphone虽然不是第一个使用重力感应的手机,却把它发挥到极致, 并引领了一股风潮, 对于手机用户来说,是一次体验上的革命.

 不过,我只能说手机的发展速度实在是太快, 重力感应刚兴起,iphone4已经把电子陀螺仪这个东东用在了手机上, 下一个时代可能就是电子陀螺仪了, 有了这个东东,精确计算手机的运动轨迹就不是问题。这是题外话。

 

M8是通过一个加速度传感器,检测手机上三个坐标方向的加速度,原理应该是通过不同的角度电信号的不同,通过AD转换,输出数字信号。 这只是本人根据一般加速度传感器的原理做的猜想, 因为没有查到m8所用加速度传感器的芯片型号, 无法找到它的datasheet.

 

重力加速度传感器的量程单位一般是 g, 也就是重力加速度常量,m8支持18mg至1g之间的量程范围, 1 = 18mg, 56=1g, g = 9.8, 支持56阶的加速度精度.举个例子,如果你的m8水平的放在桌面上, 理论上得到的z轴的加速度值应该为-56, 而x,y轴上为0, 但是实际的数据跟上述会有小的偏差,这个一般可以忽略. 正常情况下,加速度值的绝对值不会超过56, 如果超出这个值,有可能是突然的动作,比如剧烈摇晃手机.一般用到加速度原理的手机应用,我们只考虑重力加速度带来的影响效果, 不考虑一般的加速度(这方面的应用也有,比如摇晃手机取消操作,切歌等).

 

3 软件设计

M8用的是ce6.0, 而CE6或win mobile本身没有官方的重力感应API接口, 当手机硬件支持的情况下, 要想在上述两个系统上实现重力感应操作, 只有两种方法,一是有些手机厂商自己做了应用层的API(比如魅族,三星也有),二是在驱动级别通过底层的指令直接操作.

 

下面就来做一个简单的应用, 这个应用是在m8 sdk中重力感应例程基础上修改的, 这个sdk里的例程问题比较多,

第一, x轴,y轴搞反了(这可是个大问题).

第二,用两个按钮分别展示x轴和y轴的平面运动轨迹,这个想法实个人认为比较失败, 应该是用一个按钮展示在一个平面上(x轴和y轴)的运行轨迹比较直观一点吧.

 

第三,运动轨迹误差太大, sdk里每隔10ms位移加或减去一个固定值(在加速 度一定的情况下), 学过物理的都知道,如果位移匀速变化,加速度为应该是0,速度是匀速, 用sdk的程序实际运行,发现手机在一定的角度时,按钮滑动的速度确实感觉不到明显的变化, 也证实了这一点.这种重力感应的应用, 误差是允许的,但这种误差就有点不真实了.

 

由加速度和位移的公式可知,当加速度固定时(比如手机固定倾斜一个角度), 位移是加速增加,它跟时间和加速度这两个分量都是成正比的, 比如, 手机倾斜一个角度, 我们模拟一个小球从手机的顶端滑动到底部, 应该可以明显看出越往底部速度越快, 这个效果才更加真实.

 

当然, 对于简单的应用,没必要按照公式来计算位移, 我们可以开启一个定时器,每隔10ms更新一次位移(就像sdk中的做法), 关键代码如下:

 

//开启acc功能
		MzAccOpen();  

		//获取XYZ轴加速度值 1 == 18mg, 56 == 1g 
		//注意以下几点, 
		//1 要先调用MzAccGetXYZ,再调用
		//MzAccGetX/MzAccGetY/MzAccGetZ后,才能获得正确的值
		//2 获得的加速度值范围是-55~+55, 绝对值起大,加速度越大. 
		//
		MzAccGetXYZ(&m_XAxis, &m_YAxis, &m_ZAxis);

		MzAccGetX(&m_XAxis);
		//获得Y轴加速度
		MzAccGetY(&m_YAxis);
		MzAccGetZ(&m_ZAxis);

		RECT rRect = MzGetWorkArea();

		m_XButton.SetPos(0, 0, 150, 100);
		AddUiWin(&m_XButton);

		m_nMaxXPos = RECT_WIDTH(rRect) - m_XButton.GetWidth();
		m_nMinXPos = 0;

		m_nMaxYPos = RECT_HEIGHT(rRect) - m_XButton.GetHeight();
		m_nMinYPos = 0;

		SetTimer(m_hWnd, 10, 10, NULL);  

		//设置初始的速度和位置
		m_XPos = m_nMinXPos;
		m_YPos = m_nMinYPos;

		m_YSpeed = 0;
		m_XSpeed = 0;

		m_nCount = 0;

		return TRUE;
	}

	virtual void OnTimer(UINT_PTR nIDEvent)
	{
		switch(nIDEvent)
		{
		case 10:
			{
				//获得X轴加速度
				MzAccGetX(&m_XAxis);
				//获得Y轴加速度
				MzAccGetY(&m_YAxis);

				m_nCount++;
				if ( (m_nCount%10) == 0)
				{
					m_XSpeed += 2;
					m_YSpeed += 2;
				}

				if (IsXDirectionChange(m_XAxis))
				{
					m_YSpeed = 0;
				}
				if (IsYDirectionChange(m_YAxis))
				{
					m_XSpeed = 0;
				}

				//计算控件的Y位置,注意用的是加X轴的坐标
				if (m_XAxis < 0)
				{
					m_XAxis = -m_XAxis;
					m_YPos = m_YPos + m_YSpeed + m_XAxis;
				}
				else
				{
					m_YPos = m_YPos - m_YSpeed - m_XAxis;
				}

				if (m_YPos < m_nMinYPos)//最底端
				{
					m_YSpeed = 0;//注意这里要重置,防止溢出
					m_YPos = m_nMinYPos;
				}

				if (m_YPos > m_nMaxYPos)//滑动到最顶端
				{
					m_YPos = m_nMaxYPos;
					m_YSpeed = 0;
					//SetTimer(m_hWnd, 11, 10, NULL);
				}

				//计算控件的X位置
				if (m_YAxis < 0)
				{
					m_YAxis = - m_YAxis;
					m_XPos = m_XPos - m_XSpeed - m_YAxis;
				}
				else
				{
					m_XPos = m_XPos + m_XSpeed + m_YAxis;
				}

				if (m_XPos < m_nMinXPos)
				{
					m_XSpeed = 0;
					m_XPos = m_nMinXPos;
				}

				if (m_XPos > m_nMaxXPos)
				{
					m_XSpeed = 0;
					m_XPos = m_nMaxXPos;
				}

				//重新设定控件的位置
				m_XButton.SetPos(m_XPos, m_YPos, 150, 100);
				Invalidate();
				//UpdateWindow();
			}
			break;
		default:
			break;
		}
	}
};

上述代码均在定时器处理函数中, 注释写得比较详细了, 要说明一下IsXDirectionChange和IsYDirectionChange两个函数, 这两个函数可以判断加速度方向是否更改, 如果更改, 把m_XSpeed置0, 这个也是为了逼近真实的效果. 试想一下, 当小球滑动的时候, 手机突然改变方向, 小球运动的速度应该是要从0开始了.

 

把程序放在小8里运跑一下, 效果还不错(可以在这人基础上做平衡球游戏了, 呵呵),截个图。

 

M8下开发重力感应程序_第2张图片

你可能感兴趣的:(游戏,api,null,iPhone,手机)