TI-BASIC 计算器游戏开发之文字、图形、音频教程 II:图形处理

TI-BASIC 计算器游戏开发之文字、图形、音频教程 II:图形处理

【第二部分】
TI-BASIC 图形处理教程
还没到结束的时候,我们查看一下内存,就会发现,一个8*8的汉字,用点阵数据保存,只需要 8 byte,但是用行列坐标数据保存,行坐标和列坐标都需要好多个 byte 来保存,这就是空间换时间的策略,不过这个行列坐标确实太占地方了,我们看看怎么把它再压缩一下,不妨继续粗暴一下,把这个已经显示到屏幕上的汉字截个图如何?反正就那几个点,这里要用到 TI-BASIC 的另一个函数 StoPic ,专门保存屏幕图形的,用法如下:

StoPic picName,raw,col,weith,heigth

意思就是把计算器屏幕上,先找到坐标为(raw,col)的点,从这个点出发,向右宽度为 weigth,向下高度为 heigth 的矩形区域内的图形保存到图形变量 picName 里,现在查看一下内存,看看这个 picName 只占了很少的几个 byte ,你就会觉得我们这么从点阵图到坐标值,再从坐标值到图形变量折腾来折腾去还是有所收获的。以后就可以通过直接调用这个图形变量来显示这个图形。

这样我们就可以把游戏中用到的汉字先转换为行列坐标列表数据,再转换为图形变量数据,就可以在程序中使用汉字了,这其实也是一种适合TI-89T下显示汉字的解决方案。

【局限性】只能在你自己的程序中显示汉字,没办法在TI自己的程序中显示汉字菜单,没怎么研究过汉化技术,理论上应该是可以的,因为程序菜单显示英文其实也是调用的英文字符的点阵图形,不过在TI计算器上搞估计比较麻烦,所以就不深入研究了。

简单说一下在屏幕上显示图形变量的函数,TI-BASIC提供了多个函数来通过调研内存中的图形变量来显示图形,有RlcPic,RplcPic,XorPic,AndPic,OrPic,这些函数的功能有细微的差别,具体可以查看TI-89T的手册,我们这里会用到RlcPic,RplcPic,XorPic这3种。
先说RplPic,用法如下:

RplPic picName,raw,col

上面的语句直接把计算器内存中保存为 picName 的图形绘制到左上角坐标为 (raw,col) 的区域内,那么右下角坐标就是 (raw + heigth , col + weigth),所以在用这条语句时一定要注意计算好位置,免得因为你的坐标值超过了屏幕范围而出错。

用这个函数可以把你指定的汉字图形显示在屏幕上的任何位置,等等,任何位置?那么如果用循环语句来让raw和col递增会如何呢?聪明,递增或者递减都会让汉字图形在屏幕上动起来,这个就是动态图形的基本原理,短时间内让指定图形不停地在不同的位置出现,那么我们用循环来试试,代码如下:

先来一个向右平行移动的

For i,1,30,1
 RplPic picName,raw,col+i
EndFor

哈,是不是发现图形经过的位置都变成一道黑影了,为什么会这样呢?因为你只是把图形画到一个位置上,然后改变坐标值,再把它画到新的位置上,但是你没去管原来位置的图形,所以只需一会儿功夫你的屏幕就被画满了,怎么办?先把原来位置的图形擦掉,再画到新位置,然后再把新位置的图形擦掉,再画到下一个新位置,这样就可以实现清晰的动态图形效果了。
这里需要用到擦除图形的函数,TI-BASIC提供了两个类似的函数: PxlOff 和 XorPic ,一看就明白,PxlOff 是操作像素点的,XorPic 是操作图形变量的,我们现阶段需要的是 XorPic,XorPic 有个好处,就是第一次执行时是画图,第二次在同一个坐标执行时就是擦图了,也就是说原来的位置如果有图,就擦掉它,原来位置如果没有图就显示它,是不是不太好理解?没关系,实际执行几个例子就清楚了,具体用法如下:

XorPic picName,raw,col

那么上面的例程就改成这样:
向右平行移动,raw不变,只要把col的值循环增加就可以了

For i,1,80,1
 XorPic picName,raw,col+i
 XorPic picName,raw,col+i
EndFor

向下平行移动,col不变,只要把raw的值循环增加就可以了

For i,1,80,1
 XorPic picName,raw+i,col
 XorPic picName,raw+i,col
EndFor

向左平行移动是raw不变,把col循环减少:

For i,1,80,1
 XorPic picName,raw,col-i
 XorPic picName,raw,col-i
EndFor

向上平行移动是col不变,把raw值循环减少。

For i,1,80,1
 XorPic picName,raw-i,col
 XorPic picName,raw-i,col
EndFor

有人希望能斜着移动,这个问题提得好,斜着移动也有4个方向,只要同时改变raw和col的值就可以了,那么怎么写程序呢?有人想用两个循环,嘿嘿,那就错了,仔细想一下就明白为什么错了,实际只要这样就行:raw+i,col+i,不过这么移动太单调了,你可以给raw增加的i值乘以一个系数,比如0.5,结果就是这样 raw+0.5*i,col+i ,程序就是这样的;

For i,1,80,1
 XorPic picName,raw+0.5*i,col+i
 XorPic picName,raw+0.5*i,col+i
EndFor

使用不同的系数就会以不同的角度斜方向移动。

又有人说了,你移动来移动去都是直线移动,能不能搞个曲线移动,比如迫击炮的炮弹就是抛物线的运动轨迹,地球绕太阳那是椭圆的移动轨迹,很好,我只能说你非常有思想,让我们一起来思考一下,先在 For 的框架内实现,搞个抛物线的运动轨迹,很显然,需要抛物线的方程了,比如用这个最简单的  y = x*x ,我们知道前面的循环主要是拿循环变量 i 作为坐标值的增量(假设为j),也就是说直接使用了i = j ,然后raw和col分别增加i和j,注意这里用的是“+”,也就是说变化后的坐标值跟原值是一种线性变化,而且没哟考虑raw和col之间的关系,那么我们现在要让图形沿着抛物线运动,需要在raw和col之间建立一种对应变化关系,应该满足抛物线方程,具体说就是:

 raw = col*col

或者

col = raw*raw

记住这时就不能简单地把增量加到坐标值上去了,我们可以验证一下,程序如下:

raw = col*col
For i,1,80,1
 XorPic picName,raw,col
 XorPic picName,raw,col
EndFor

这里验证了 raw = col*col 的情况,还有  col = raw*raw 的情况,自己验证,不要偷懒啊!

嘿嘿,有人又提问了,上面提到的所有的移动都是保持图形点阵本身的行平行于屏幕,能不能让图形旋转着移动呢?很好,举一反三地提问我最喜欢了,我们先明确定义一下什么是图形的旋转移动,具体说就是点阵图形中的某一像素点的坐标不变,其他像素点以这个点为圆心,顺时针或者逆时针旋转同样的角度,注意这里作为圆心的像素点可以是有内容的,也可以是空白点,既然旋转问题的需求已经清晰地分析出来了,那么问题的解决方案也基本有了,像这种角度计算就不可避免地用到三角函数了,或者自己用距离比值来计算也可以。

一些高级语言会内置的这种旋转图形的操作函数,比如C语言,不过TI-BASIC貌似没提供这个功能,那么我们就自己写一个,经过上述分析,我们发现想要旋转图形,必须做到的就是计算每个像素点到圆点的距离,并提供一个旋转角度作为参数(包括顺时针和逆时针),然后每个点都以自己到圆心的距离作为半径,按照指定角度进行旋转。
好在需要画在屏幕上的是那些黑色点,空白点是不需要考虑得,因此可以节省一点计算量。当然了这个算法只是揭示这种图形变换的基本原理,具体实现时会有很多不同的选择,比如最常见的就是拿坐标数据跟不同类型的矩阵进行计算,来达到各种不同的变换效果,因为矩阵运算的算法不太直观,这里就不写了,感兴趣的拼音可以自行研究,我们的算法代码如下:
(实际还没写这段代码,后面补)

很好,现在对于这个图形的处理已经基本圆满了,什么?有人说我们搞了半天都是在二维平面上打转转,想做一个三维立体空间里的图形变换,太好了,看来我们的讨论又深入了,按照我们解决问题的一贯手段,先来分析三维空间的运动,首先是让我们的图形前进和后退,换句话说也就是放大和缩小,放大好办,比如8*8的图形,每个像素点扩充4倍,变成32*32,从一个“口”字型变为一个“田”字型,不光黑色点要扩充,白色点也要扩充,这样一个图形就变大了,看起来就好像是离它更近了,那么如果持续地做这种变化,带来的效果就是图形好像在朝我们走近一样。这种变化是三维空间变化的基础,其他方式的变换都可以在此基础上推导得出,再结合前面提到的各种平行移动、斜线移动、曲线轨迹移动以及三角函数旋转等方法,我们的图形想要实现各种三维空间里的移动就都不成问题了。

说到这里,想必有人也看出来了,计算机上所有的图形处理,说到底就是对图形坐标值的计算,只要预先设置好计算的方法,基本上就没什么神秘了,唯一限制的因素就是计算量的大小,因此程序员们想出了各种技巧来回避复杂计算,用简单计算来取代,以便提升效率。比如求三角函数时可以用查表法来代替计算,这种思想在人类历史上由来已久,在人类还没有发明电子计算机前,人类就把各种角度的三角函数值预先计算出来,然后印刷成书,等到使用时直接查表就可以获取到较为精确的数值,这样就避免了每次的计算。可见提升效率的思路是一致的,这种简化思路正是我前面提到过的“以空间换时间”,当然也可以逆过来用,以“时间换空间”。这里再给一个放大缩小的例子:

(实际还没写这段代码,后面补)

其他的各种三维空间的变换算法就不再一一列举了,自己钻研吧,最好能设计出高效的算法,写成函数,这样就能被其他人使用了,呵呵。

【更多的思考】另外还需要考虑鉴于这种计算的结果不完全是整数值,需要进行四舍五入后才能做为新坐标使用,如果有两个相邻点经过旋转计算的四舍五入之后重叠了该怎么办?(这就意味着图形被有损压缩了),下次再旋转时它们按照一个点来算还是按照两个点来算,如果按两个点来算,是否需要保存原来计算得到的四舍五入之前的数值?以便在下次计算时提供精确的输入,以避免这种因误差引起的信息损失。可见一种算法如果想要做得更完善,满足更多的意外场景,是没有止境的,

【提示】在软件开发的很多时候,如果我们能把一个功能需求清晰地描述出来,那就意味着这个功能需求的具体算法也出来了,或者当我们能够清晰描述出某些高难度的需求时,我们同时也会清楚这个需求是否能在现有系统上实现。是不是图形开始旋转了,很好,这就是图形旋转的数学原理,是不是觉得很简单?确实很多东西的基本原理都是非常简单的。还有无数的典型数学函数可以放到坐标增量来玩,比如什么对数函数、指数函数等等。

现在既然图形已经动起来了,我们稍微关注一下图形的动态效果,是不是发现移动得很慢,而且闪烁得很厉害,都快成了淡淡的灰影了,怎么办?简单,调整我们的参数,移动得慢是因为移动步子迈得小,把 For 语句最后一个参数 step 修改得大一些,图形就跑得快多了,图形太淡是因为画图和擦图的间隔太短,所以它在屏幕上就显示得太淡,唯一的办法就是画完图形之后不要马上擦,停留那么一小会儿,还以向右平行移动为例:

For i,1,80,1
 XorPic picName,raw,col+i
 Loop
  u+1->u
 EndLoop
 XorPic picName,raw,col+i
EndFor

 这里我们在画图和擦图命令之间加了一个累加的循环,加到一定值之后停止循环,可以通过设置这个值的大小来控制中间的停顿时间。(也许还有其他更好的办法,期待有人给出)。

常用的图形操作就这些内容了,基本上掌握了这些就可以在TI-89T计算器上做出动画片头、动画效果来了,后面讲一下如何通过键盘来控制图形在屏幕上的运动。

转载于:https://my.oschina.net/freeblues/blog/64605

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
简介一年多以前,Android平台曾经出现过三个流行的TI计算器模拟器软件,分别包括TI-83、TI-85、TI-86,让许多用户大为欣喜,不过因为这些软件采用了一键安装模式导致侵犯了德州仪器的版权问题,最终这些软件被迫下架。 现在TI-89计算器又出现在Android平台,这次为了避免重蹈覆辙,开发者采用了模拟机的方式,仅提供一个模拟器,用户需要自行下载德州仪器给出的计算器ROM用来给软件加载。 虽然现在这款模拟器还处于测试阶段,但是已经可以正常使用,而且是Android平台上出现的第一个可用的TI-89计算器工具更新内容: - 优化变焦模式 - 增加振动器开/关 - 性能改进 - 改善应用程序的链接 安装说明:下载主程序和rom文件,解压zip格式的rom文件,再把解压后的文件放到SD卡任意目录,安装主程序,打开主程序并按菜单键,选择Load ROM,点击刚放到SD卡的rom文件,重新运行程序即可! 。可以成功模拟五种计算器: TI89,TI89Titanium,TI92,TI92plus,Voyage200。 安装使用方法步骤: 1:把rom包解压到sd卡根目录(TI89Titanium_OS.89u为解压后的rom包)。 2:安装TI89主程序,点击菜单点击ROM Manager(看截图1)。 3:点击Add Rom(看截图2)。 4:点击Browse(看截图3)。 5:向下滑动找到刚才解压后的rom包TI89Titanium_OS.89u,点击它(看截图4)。 6:点击Select Type,再滑动选择TI89或TI92或其它三个(TI83和84系列不可用,可能比较落后,模拟器不支持,建议用TI89和TI92或Voyage200系列)(看截图5)。 注意:关闭软件方法,按住2nd键不放,再按ON键,然后放开手指即可退出软件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值