当前位置: 首页 > news >正文

Nokia UI学习范例FishTank研究

作者:mingjava 文章来源:http://www.j2medev.com/Article/ShowArticle.asp?ArticleID=153

由于MIDP1.0中提供的API比较有限,因此Nokia实现了自己的类库来提供补充。其中包括声音的支持、屏幕的背景光和机器震动、图像的翻转、Alpha通道以及对像素的操作支持。学习Nokia UI的使用的最好例子莫过于Nokia官方提供的FishTank了。本文讲主要介绍一下这个范例,其中的一些思路和技巧是值得我们学习的。

FishTank的界面比较简单,只有一个屏幕。池塘里的鱼儿不停的游动,水底的水草也不停的漂浮。这个界面是分层设计的,因此引入了一个变量z,这样就和水平参数x和垂直参数y构成了三维的空间。其中水草处于中间层。鱼的游动是无规律的,其中的算法我们可以参考,当鱼触及到边缘的时候,它会反向游动。通过Nokia UI中提供的水平翻转可以实现。dg.drawImage(img, x, y, (Graphics.LEFT | Graphics.TOP),DirectGraphics.FLIP_HORIZONTAL);水草的游动也是随机的

下面我们看看整个应用的结构

程序总共有四个类组成,其中我们主要关注的是FishTankCanvas、Fish和Weeds。其中Fish和Weeds比较相似,他们代表了两个对象鱼儿和水草。而FishTankCanvas是FullCanvas的子类并且实现了Runnable接口,它是一个独立的线程。每隔一段时间他会更新一下Fish和Weeds的状态,然后重新绘制屏幕。run()方法中的代码如下
public void run()
{
Thread currentThread = Thread.currentThread();

try
{
// This ends when animationThread is set to null, or when
// it is subsequently set to a new thread; either way, the
// current thread should terminate
while (currentThread == animationThread)
{
long startTime = System.currentTimeMillis();

// Only animate when the canvas is visible.
if (isShown())
{
tick();

// Repaint everything above the sand, the fish
// never swim at h > waterHeight.
repaint(0, 0, waterWidth, waterHeight);
serviceRepaints();
}

long timeTaken = System.currentTimeMillis() - startTime;
if (timeTaken < MILLIS_PER_TICK)
{
synchronized (this)
{
wait(MILLIS_PER_TICK - timeTaken);
}
} else
{
currentThread.yield();
}
}
} catch (InterruptedException e)
{
}
}
由于在屏幕的下方有一部分是泥土,因此在这里调用了repaint(0,0,waterWidth,waterLength)。其实FishTankCanvas同时也是一个容器类,它是Fish和Weeds的容器。他去更新Fish和Weeds的状态然后调用各自的draw()方法来重新绘制。下面我们看看FishTankCanvas是如何绘制的
private synchronized void drawFishTank(Graphics g)
{
// Draw the water
g.setColor(0, 255, 255);
g.fillRect(0, 0, waterWidth, waterHeight);

// Draw the sand
g.setColor(255, 128, 64);
g.fillRect(0, waterHeight, waterWidth, getHeight());

// Draw the weeds and fishes
for (int plane = 0; plane < NUM_PLANES; plane++)
{
if (plane == WEEDS_PLANE)
{
weeds.draw(g);
}

for (int i = 0; i < fishes.size(); i++)
{
Fish fish = (Fish) (fishes.elementAt(i));
if (fish.getZ() == plane)
{
fish.draw(g);
}
}
}
}

接下来我们研究一下Fish和Weeds的代码,它们就是有很多图片构成的。实现的结果和MIDP2.0中的Sprite差不多。Fish和Weeds的图片都是有类型之分的,每个类型又有几个桢。这样才可以构造出不同的对象,并且相同的对象在不同的时刻也有不同的状态。
private static final int TYPE_NUM = 3;

private static final int FRAME_NUM = 2;

private static final Image[][] fishImage;
Fish和Weeds都是采用了静态初始化块的方式来初始化相应的二维数组。例如
static
{
fishImage = new Image[TYPE_NUM][FRAME_NUM];

int i = 0;
int k = 0;
try
{
for (i = 0; i < TYPE_NUM; i++)
{
for (k = 0; k < FRAME_NUM; k++)
{
fishImage[i][k] = Image.createImage("/fish" + i + k
+ ".png");
}
}
} catch (java.io.IOException e)
{
fishImage[i][k] = null;
}

// This MIDlet implicitly assumes that all the Images
// are the same width and height.

fishWidth = fishImage[0][0].getWidth();
fishHeight = fishImage[0][0].getHeight();
}

为了让鱼儿或者水草具有更好的随机性,代码是通过如下的算法来控制他们的方向的,下面以方向x为例说明
// mostly continue as we are, but sometimes randomly change
if ((ticksSinceLastChangeX > 20) && (rand(20) == 0))
{
vx = rand(2) * 2 - 1; // -1 or 1
ticksSinceLastChangeX = 0;
}

// if moving would take us off the left or right of the water,
// reverse
if (((vx < 0) && (x + vx < 0))
|| ((vx > 0) && (x + fishWidth + vx > FishTankCanvas.waterWidth)))
{
vx = -vx;
ticksSinceLastChangeX = 0;
}
当鱼接触到水的边缘的时候,它的速度方向会改变。在此前的代码是为了增加他的随机性。Fish的重新绘制也比较简单,这里用到了Nokia UI中的水平翻转的扩展功能
public void draw(Graphics g)
{
DirectGraphics dg = DirectUtils.getDirectGraphics(g);

Image img = fishImage[type][frame];
if (img != null)
{
if (vx < 0)
{
dg.drawImage(img, x, y, (Graphics.LEFT | Graphics.TOP),
DirectGraphics.FLIP_HORIZONTAL);
} else
{
dg.drawImage(img, x, y, (Graphics.LEFT | Graphics.TOP), 0);
}
}

frame = (frame + rand(2)) % FRAME_NUM;
}

我们可以看到每次绘画结束后都会把frame的编号随机设置一下,这样可以得到鱼儿本身运动的效果。

MIDlet的代码比较简单,直接给出
package example.fishtank;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

public class FishTankMIDlet extends MIDlet
{
private final FishTankCanvas canvas;

public FishTankMIDlet()
{
canvas = new FishTankCanvas(this);
}

public void startApp()
{
Display.getDisplay(this).setCurrent(canvas);
canvas.start();
}

public void pauseApp()
{
canvas.stop();
}

public void destroyApp(boolean unconditional)
{
canvas.stop();
}

/*
* On the exit command, cleanup and notify that the MIDlet has been
* destroyed.
*/
void exitRequested()
{
destroyApp(false);
notifyDestroyed();
}
}

总结:我们在本文中可以学到如何使用Nokia UI中提供给我们的扩展功能,比如水平翻转、全屏显示等。更重要的是,FishTank的代码设计比较合理,代码思路清晰。比较容易维护和扩展。另外程序中随机性的算法也可以用于实际工作中。您可以从这里下载全部代码点击浏览该文件

相关文章:

  • react 向事件处理程序传递参数
  • react 有状态组件 切换登陆和未登录状态以及UI展示
  • 整合SE J2ME SDK与eclipse开发环境
  • MP3在Sony Ericsson K700上的音响效果
  • K700之图像内存处理
  • react 隐藏组件 阻止渲染
  • react 数组map方法转化列表
  • 使用索爱V800开发流媒体应用程序
  • 读取索爱手机固件版本信息和IMEI号
  • react jsx中使用map
  • 在基于MIDP的应用程序上使用JDBC
  • react 表单使用受控组件的思想
  • 索爱部分机型支持同时播放多个声音
  • react状态提升 两个子组件状态共享 让子组件状态提升 通过公有父组件props的方法传递回调函数执行改变( handleChange(e) { // 之前的代码: this.setSt)
  • SonyEricsson发布更好支持企业级应用的新JSR
  • 【EOS】Cleos基础
  • 【技术性】Search知识
  • 2018一半小结一波
  • 2019.2.20 c++ 知识梳理
  • Bootstrap JS插件Alert源码分析
  • Debian下无root权限使用Python访问Oracle
  • exif信息对照
  • IIS 10 PHP CGI 设置 PHP_INI_SCAN_DIR
  • JAVA之继承和多态
  • MQ框架的比较
  • node和express搭建代理服务器(源码)
  • Python - 闭包Closure
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • use Google search engine
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • 从setTimeout-setInterval看JS线程
  • 更好理解的面向对象的Javascript 1 —— 动态类型和多态
  • 开源中国专访:Chameleon原理首发,其它跨多端统一框架都是假的?
  • 理解在java “”i=i++;”所发生的事情
  • 码农张的Bug人生 - 见面之礼
  • 如何使用Mybatis第三方插件--PageHelper实现分页操作
  • 数组的操作
  • 项目管理碎碎念系列之一:干系人管理
  • 小试R空间处理新库sf
  • 一个普通的 5 年iOS开发者的自我总结,以及5年开发经历和感想!
  • 原生JS动态加载JS、CSS文件及代码脚本
  • SAP CRM里Lead通过工作流自动创建Opportunity的原理讲解 ...
  • $refs 、$nextTic、动态组件、name的使用
  • (1)SpringCloud 整合Python
  • (ibm)Java 语言的 XPath API
  • (LeetCode 49)Anagrams
  • (Mirage系列之二)VMware Horizon Mirage的经典用户用例及真实案例分析
  • (动手学习深度学习)第13章 计算机视觉---微调
  • (附源码)springboot猪场管理系统 毕业设计 160901
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (附源码)基于SpringBoot和Vue的厨到家服务平台的设计与实现 毕业设计 063133
  • (南京观海微电子)——COF介绍
  • (亲测有效)解决windows11无法使用1500000波特率的问题
  • (四)JPA - JQPL 实现增删改查
  • (淘宝无限适配)手机端rem布局详解(转载非原创)