<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Java &#38; Game &#187; j2me</title>
	<atom:link href="http://www.javagg.com/archives/category/j2me/feed" rel="self" type="application/rss+xml" />
	<link>http://www.javagg.com</link>
	<description>java&#38;j2me</description>
	<lastBuildDate>Sat, 02 Jul 2011 08:59:18 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>J2ME中RMS的使用解析</title>
		<link>http://www.javagg.com/archives/825</link>
		<comments>http://www.javagg.com/archives/825#comments</comments>
		<pubDate>Wed, 20 Oct 2010 02:36:48 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[rms]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=825</guid>
		<description><![CDATA[在J2ME中，RMS作为唯一的永久性存储工具，其重要性是不言而喻的。但是很多刚刚开始学习J2ME的新人总是抱怨在这方面的资料很少，或者是针对性不强。因此，我想把自己在这方面的一些学习心得和大家交流一下。
RMS即Record Manager System，在手机应用中常常作为得分记录、游戏信息存储等的工具使用。
RMS的使用可以分为两个部分：一、单一记录的构造；二、RecordStore的使用和操作。下面就这两方面进行详细说明。
一、单一记录的构造。我们在存储记录时可能需要记录很多相似的条目，在这里我们可以把这种结构看成数据库，我们在这一步就是要构造数据库中的一行，即单一记录的构造。程序的源码如下：



&#160;


package com.cuilichen.usual;


&#160;


import java.io.ByteArrayInputStream;//要使用到的各种输入输出流


import java.io.ByteArrayOutputStream;


import java.io.DataInputStream;


import java.io.DataOutputStream;


&#160;


public class Appointment &#123;//单一记录的类名


private int int1; //


private int int2; //


private long long1;


private String str1; //str1作为保留字段，记录检索的关键字


private String str2; //


private String str3; //


private boolean WroteFlag; //


&#160;


public Appointment&#40;&#41; &#123;


&#125;


&#160;


public Appointment&#40;int _int1, int _int2, long _long1, String _str1,


String _str2, String _str3, boolean _WroteFlag&#41; &#123;


this.int1 = _int1; //写入RMS的构造函数


this.int2 = _int2;


this.long1 = _long1;


this.str1 = [...]]]></description>
			<content:encoded><![CDATA[<p>在J2ME中，RMS作为唯一的永久性存储工具，其重要性是不言而喻的。但是很多刚刚开始学习J2ME的新人总是抱怨在这方面的资料很少，或者是针对性不强。因此，我想把自己在这方面的一些学习心得和大家交流一下。<br />
RMS即Record Manager System，在手机应用中常常作为得分记录、游戏信息存储等的工具使用。<br />
RMS的使用可以分为两个部分：一、单一记录的构造；二、RecordStore的使用和操作。下面就这两方面进行详细说明。<br />
一、单一记录的构造。我们在存储记录时可能需要记录很多相似的条目，在这里我们可以把这种结构看成数据库，我们在这一步就是要构造数据库中的一行，即单一记录的构造。程序的源码如下：<span id="more-825"></span></p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">package</span> com.<span class="me1">cuilichen</span>.<span class="me1">usual</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">import java.io.ByteArrayInputStream;//要使用到的各种输入输出流</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co2">import java.io.ByteArrayOutputStream;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">import java.io.DataInputStream;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="co2">import java.io.DataOutputStream;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">class</span> Appointment <span class="br0">&#123;</span><span class="co1">//单一记录的类名</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">private</span> <span class="kw4">int</span> int1; <span class="co1">//</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <span class="kw4">int</span> int2; <span class="co1">//</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <span class="kw4">long</span> long1;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str1; <span class="co1">//str1作为保留字段，记录检索的关键字</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str2; <span class="co1">//</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">private</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str3; <span class="co1">//</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">private</span> <span class="kw4">boolean</span> WroteFlag; <span class="co1">//</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> Appointment<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> Appointment<span class="br0">&#40;</span><span class="kw4">int</span> _int1, <span class="kw4">int</span> _int2, <span class="kw4">long</span> _long1, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> _str1,</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> _str2, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> _str3, <span class="kw4">boolean</span> _WroteFlag<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">this</span>.<span class="me1">int1</span> = _int1; <span class="co1">//写入RMS的构造函数</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">this</span>.<span class="me1">int2</span> = _int2;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">this</span>.<span class="me1">long1</span> = _long1;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">this</span>.<span class="me1">str1</span> = _str1;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">this</span>.<span class="me1">str2</span> = _str2;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">this</span>.<span class="me1">str3</span> = _str3;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">this</span>.<span class="me1">WroteFlag</span> = _WroteFlag;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> Appointment<span class="br0">&#40;</span><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> rec<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">initAppointmnet<span class="br0">&#40;</span>rec<span class="br0">&#41;</span>; <span class="co1">//读取RMS内容的构造函数</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> toBytes<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//写成字节</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> data = <span class="kw2">null</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AByteArrayOutputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">ByteArrayOutputStream</span></a> baos = <span class="kw2">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AByteArrayOutputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">ByteArrayOutputStream</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ADataOutputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">DataOutputStream</span></a> dos = <span class="kw2">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ADataOutputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">DataOutputStream</span></a><span class="br0">&#40;</span>baos<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">writeInt</span><span class="br0">&#40;</span>int1<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">writeInt</span><span class="br0">&#40;</span>int2<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">dos.<span class="me1">writeLong</span><span class="br0">&#40;</span>long1<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">writeUTF</span><span class="br0">&#40;</span>str1<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">writeUTF</span><span class="br0">&#40;</span>str2<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">writeUTF</span><span class="br0">&#40;</span>str3<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">writeBoolean</span><span class="br0">&#40;</span>WroteFlag<span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">data = baos.<span class="me1">toByteArray</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">baos.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">dos.<span class="me1">close</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">e.<span class="me1">printStackTrace</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> data;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw4">void</span> initAppointmnet<span class="br0">&#40;</span><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> rec<span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//从字节读取内容</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AByteArrayInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">ByteArrayInputStream</span></a> bais = <span class="kw2">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AByteArrayInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">ByteArrayInputStream</span></a><span class="br0">&#40;</span>rec<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ADataInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">DataInputStream</span></a> dis = <span class="kw2">new</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3ADataInputStream+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">DataInputStream</span></a><span class="br0">&#40;</span>bais<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">int1 = dis.<span class="me1">readInt</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">int2 = dis.<span class="me1">readInt</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">long1 = dis.<span class="me1">readLong</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">str1 = dis.<span class="me1">readUTF</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">str2 = dis.<span class="me1">readUTF</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">str3 = dis.<span class="me1">readUTF</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">WroteFlag = dis.<span class="me1">readBoolean</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">e.<span class="me1">printStackTrace</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw4">int</span> getInt1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//int</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> int1;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">public</span> <span class="kw4">int</span> getInt2<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> int2;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw4">long</span> getLong1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> long1;</div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getStr1<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//String</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> str1;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getStr2<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//String</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> str2;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">public</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> getStr3<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> str3;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw4">boolean</span> getWroteFlag<span class="br0">&#40;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span> <span class="co1">//返回写入标志</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">return</span> WroteFlag;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>这个类的使用保证了我们在使用流时，内容的写入和输出。当然，就如同数据库表的设计一样，我们可以任意对每一条记录增加或减少字段，在上面的类中我只使用了int1，int2，long1，str1，str2，str3和WroteFlag一共7个字段<br />
二、RecordStore的操作。类RMS如下：</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">package</span> com.<span class="me1">cuilichen</span>.<span class="me1">usual</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="co2">import javax.microedition.rms.RecordEnumeration;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="co2">import javax.microedition.rms.RecordStore;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">class</span> RMS <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">final</span> <span class="kw4">int</span> Int1 = <span class="nu0">0</span>;<span class="co1">//各个字段的默认数值</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">final</span> <span class="kw4">int</span> Int2 = <span class="nu0">0</span>;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">final</span> <span class="kw4">long</span> Long1 = <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> Str1 = <span class="st0">&quot;&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> Str2 = <span class="st0">&quot;&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw2">final</span> <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> Str3 = <span class="st0">&quot;&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">boolean</span> addRecord<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name, <span class="kw4">int</span> int1, <span class="kw4">int</span> int2,<span class="co1">//添加记录</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">long</span> long1, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str1, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str2, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str3, <span class="kw4">boolean</span> b<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">boolean</span> success = <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">RecordStore rs = RecordStore.<span class="me1">openRecordStore</span><span class="br0">&#40;</span>name, <span class="kw2">true</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">Appointment app = <span class="kw2">new</span> Appointment<span class="br0">&#40;</span>int1, int2, long1, str1, str2,str3, b<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//既然str1作为保留字段，我们在这里就要如此操作：例如int1为我们设定的关键字，那么str1 = Integer.toString(int1);</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> data = app.<span class="me1">toBytes</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">rs.<span class="me1">addRecord</span><span class="br0">&#40;</span>data, <span class="nu0">0</span>, data.<span class="me1">length</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">rs.<span class="me1">closeRecordStore</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">success = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">e.<span class="me1">printStackTrace</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">return</span> success;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">int</span> getNumOfRecords<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name<span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="co1">//得到RMS中记录的条数</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">RecordStore rs = RecordStore.<span class="me1">openRecordStore</span><span class="br0">&#40;</span>name, <span class="kw2">true</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> rs.<span class="me1">getNumRecords</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> <span class="nu0">0</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> Appointment<span class="br0">&#91;</span><span class="br0">&#93;</span> getRecords<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name<span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="co1">//取得RMS中的所有记录</span></div>
</li>
<li class="li1">
<div class="de1">Appointment<span class="br0">&#91;</span><span class="br0">&#93;</span> result = <span class="br0">&#123;</span> <span class="br0">&#125;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">RecordStore rs = RecordStore.<span class="me1">openRecordStore</span><span class="br0">&#40;</span>name, <span class="kw2">false</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">RecordEnumeration re = rs.<span class="me1">enumerateRecords</span><span class="br0">&#40;</span><span class="kw2">null</span>, <span class="kw2">null</span>, <span class="kw2">false</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">result = <span class="kw2">new</span> Appointment<span class="br0">&#91;</span>rs.<span class="me1">getNumRecords</span><span class="br0">&#40;</span><span class="br0">&#41;</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; result.<span class="me1">length</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">int</span> j = re.<span class="me1">previousRecordId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">Appointment app = <span class="kw2">new</span> Appointment<span class="br0">&#40;</span>rs.<span class="me1">getRecord</span><span class="br0">&#40;</span>j<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">result<span class="br0">&#91;</span>i<span class="br0">&#93;</span> = app;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="co1">//System.out.println(&quot;app[&quot;+i+&quot;] &quot;+app.getStr2());</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">rs.<span class="me1">closeRecordStore</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> result;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw2">public</span> <span class="kw2">static</span> Appointment getRecord<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name, <span class="kw4">int</span> j<span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="co1">//根据记录编号（参数 int j）取得一条记录</span></div>
</li>
<li class="li1">
<div class="de1">Appointment result = <span class="kw2">new</span> Appointment<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">RecordStore rs = RecordStore.<span class="me1">openRecordStore</span><span class="br0">&#40;</span>name, <span class="kw2">false</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">RecordEnumeration re = rs.<span class="me1">enumerateRecords</span><span class="br0">&#40;</span><span class="kw2">null</span>, <span class="kw2">null</span>, <span class="kw2">false</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">result = <span class="kw2">new</span> Appointment<span class="br0">&#40;</span>rs.<span class="me1">getRecord</span><span class="br0">&#40;</span>j<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">rs.<span class="me1">closeRecordStore</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> result;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">int</span> getIndex<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> content<span class="br0">&#41;</span> <span class="br0">&#123;</span><span class="co1">//得到记录号int j，这里需要使用保留字段str1</span></div>
</li>
<li class="li2">
<div class="de2">RecordStore rs = <span class="kw2">null</span>;</div>
</li>
<li class="li1">
<div class="de1">RecordEnumeration re = <span class="kw2">null</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">rs = RecordStore.<span class="me1">openRecordStore</span><span class="br0">&#40;</span>name, <span class="kw2">false</span><span class="br0">&#41;</span>; <span class="co1">//open</span></div>
</li>
<li class="li2">
<div class="de2">re = rs.<span class="me1">enumerateRecords</span><span class="br0">&#40;</span><span class="kw2">null</span>, <span class="kw2">null</span>, <span class="kw2">false</span><span class="br0">&#41;</span>; <span class="co1">//enumeration</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">for</span> <span class="br0">&#40;</span><span class="kw4">int</span> i = <span class="nu0">0</span>; i &lt; RMS.<span class="me1">getNumOfRecords</span><span class="br0">&#40;</span>name<span class="br0">&#41;</span>; i++<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">int</span> j = re.<span class="me1">nextRecordId</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">Appointment app = <span class="kw2">new</span> Appointment<span class="br0">&#40;</span>rs.<span class="me1">getRecord</span><span class="br0">&#40;</span>j<span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span>app.<span class="me1">getStr1</span><span class="br0">&#40;</span><span class="br0">&#41;</span>.<span class="me1">equals</span><span class="br0">&#40;</span>content<span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> j;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> <span class="nu0">1</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">public</span> <span class="kw2">static</span> <span class="kw4">boolean</span> setRecord<span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> name, <span class="kw4">int</span> id, <span class="kw4">int</span> int1, <span class="kw4">int</span> int2,<span class="co1">//设置记录号为id的记录</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">long</span> long1, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str1, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str2, <a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AString+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">String</span></a> str3, <span class="kw4">boolean</span> b<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">boolean</span> success = <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">RecordStore rs = <span class="kw2">null</span>;</div>
</li>
<li class="li2">
<div class="de2">RecordEnumeration re = <span class="kw2">null</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">try</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">rs = RecordStore.<span class="me1">openRecordStore</span><span class="br0">&#40;</span>name, <span class="kw2">false</span><span class="br0">&#41;</span>; <span class="co1">//open</span></div>
</li>
<li class="li1">
<div class="de1">re = rs.<span class="me1">enumerateRecords</span><span class="br0">&#40;</span><span class="kw2">null</span>, <span class="kw2">null</span>, <span class="kw2">false</span><span class="br0">&#41;</span>; <span class="co1">//enumeration</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">Appointment app = <span class="kw2">new</span> Appointment<span class="br0">&#40;</span>int1, int2, long1, str1, str2, str3, b<span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">//str1作为保留字段，在这里如此操作：例如若int1为我们设定的关键字，那么str1 = Integer.toString(int1);</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw4">byte</span><span class="br0">&#91;</span><span class="br0">&#93;</span> data = app.<span class="me1">toBytes</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">rs.<span class="me1">setRecord</span><span class="br0">&#40;</span>id, data, <span class="nu0">0</span>, data.<span class="me1">length</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">success = <span class="kw2">true</span>;</div>
</li>
<li class="li1">
<div class="de1">rs.<span class="me1">closeRecordStore</span><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span> <span class="kw2">catch</span> <span class="br0">&#40;</span><a href="http://www.google.com/search?hl=en&amp;q=allinurl%3AException+java.sun.com&amp;btnI=I%27m%20Feeling%20Lucky"><span class="kw3">Exception</span></a> e<span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">return</span> success;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
</ol>
</div>
<p>在这个类中，我没有将各个Exception向外抛出，一般来说这样作是不合适的，它违背了Java的异常处理机制。但是在我使用这个类的各个J2ME程序中，它是可以胜任的，所以也就没有进行进一步的修改。<br />
有了以上的两个类和你对RMS的理解，在程序中，你就可以顺畅的使用RMS了。<br />
比如在MIDlet开始时，如下操作（增加记录）：<br />
protected void startApp() throws MIDletStateChangeException {<br />
if (RMS.getNumOfRecords(rsName) = = 0) {//rsName在前面已经声明了。String rsName＝“MyRMS”；<br />
for (int i = 0; i &lt;6; i++) {<br />
RMS.addRecord(rsName, RMS.Int1, i, RMS.Long1, Integer . toString(i), RMS.Str2, &#8220;1234567890123456789&#8243;,false);<br />
}<br />
}它就在RMS中增加了6条记录，其中int1，long1，str2，WroteFlag都没有使用，我们只是使用int2，str1（作为保留字段）和str3。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/825/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>j2me经验总结之URLEncoding</title>
		<link>http://www.javagg.com/archives/815</link>
		<comments>http://www.javagg.com/archives/815#comments</comments>
		<pubDate>Wed, 25 Aug 2010 03:06:21 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=815</guid>
		<description><![CDATA[URLEncoding是用于解决链接字符串中包含中文字符的一种转换编码。各种编程环境下几乎带有它的库函数。
不过，J2ME除外。
好在JAVA的源代码中带有这个类，我们把它拷贝到J2ME环境下编译到我们的应用当中就可以了。
该文件位于JDK的目录下src.zip文件中，名叫URLEncoder.java。
但是，这个文件还需要做很多修改才能使用在J2ME环境中。
先警告大家，有几个真机，不管输入什么样的Encodeing都会出错，甚至是“UTF-8”。所以我一怒之下去除了Encodeing参数。（这可是在实际应用中得出的结论，不去掉的话可以在大部分情况下正常使用，但是，现实总是有点缺陷）
修改后的代码如下，大家请放心使用。如果有兴趣，可以比较两个代码，看看我改动了什么地方。
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
public class HURLEncoder {
 private static boolean[] dontNeedEncoding;
 static {
  dontNeedEncoding = new boolean[256];
  for (int i = 0; i &#60; 256; i++) {
   boolean b = ((i &#62;= ‘0′) &#38;&#38; (i &#60;= ‘9′))
     &#124;&#124; ((i &#62;= ‘A’) &#38;&#38; (i &#60;= ‘Z’)) &#124;&#124; ((i &#62;= ‘a’) &#38;&#38; (i &#60;= ‘z’));
   dontNeedEncoding[i] = b;
  }
  dontNeedEncoding[’ [...]]]></description>
			<content:encoded><![CDATA[<p>URLEncoding是用于解决链接字符串中包含中文字符的一种转换编码。各种编程环境下几乎带有它的库函数。</p>
<p>不过，J2ME除外。</p>
<p>好在JAVA的源代码中带有这个类，我们把它拷贝到J2ME环境下编译到我们的应用当中就可以了。</p>
<p>该文件位于JDK的目录下src.zip文件中，名叫URLEncoder.java。<span id="more-815"></span></p>
<p>但是，这个文件还需要做很多修改才能使用在J2ME环境中。</p>
<p>先警告大家，有几个真机，不管输入什么样的Encodeing都会出错，甚至是“UTF-8”。所以我一怒之下去除了Encodeing参数。（这可是在实际应用中得出的结论，不去掉的话可以在大部分情况下正常使用，但是，现实总是有点缺陷）</p>
<p>修改后的代码如下，大家请放心使用。如果有兴趣，可以比较两个代码，看看我改动了什么地方。</p>
<p>import java.io.ByteArrayOutputStream;<br />
import java.io.DataOutputStream;<br />
public class HURLEncoder {</p>
<p> private static boolean[] dontNeedEncoding;</p>
<p> static {<br />
  dontNeedEncoding = new boolean[256];</p>
<p>  for (int i = 0; i &lt; 256; i++) {<br />
   boolean b = ((i &gt;= ‘0′) &amp;&amp; (i &lt;= ‘9′))<br />
     || ((i &gt;= ‘A’) &amp;&amp; (i &lt;= ‘Z’)) || ((i &gt;= ‘a’) &amp;&amp; (i &lt;= ‘z’));</p>
<p>   dontNeedEncoding[i] = b;<br />
  }</p>
<p>  dontNeedEncoding[’ ‘] = true;<br />
  dontNeedEncoding[’-'] = true;<br />
  dontNeedEncoding[’_'] = true;<br />
  dontNeedEncoding[’.'] = true;<br />
  dontNeedEncoding[’*'] = true;<br />
 }</p>
<p> public static String encode(String s) {</p>
<p>  boolean wroteUnencodedChar = false;</p>
<p>  StringBuffer writer = new StringBuffer();</p>
<p>  StringBuffer out = new StringBuffer(s.length());</p>
<p>  for (int i = 0; i &lt; s.length(); i++) {<br />
   char c = s.charAt(i);</p>
<p>   if ((c &lt; 256) &amp;&amp; dontNeedEncoding[c]) {<br />
    if (c == ‘ ‘) {<br />
     c = ‘+’;<br />
    }</p>
<p>    out.append((char) c);<br />
    wroteUnencodedChar = true;<br />
   } else {<br />
    try {<br />
     if (wroteUnencodedChar) {<br />
      writer = new StringBuffer();<br />
      wroteUnencodedChar = false;<br />
     }</p>
<p>     writer.append(c);</p>
<p>     if (c &gt;= 0xD800 &amp;&amp; c &lt;= 0xDBFF) {<br />
      if ((i + 1) &lt; s.length()) {<br />
       int d = (int) (s.charAt(i + 1));</p>
<p>       if (d &gt;= 0xDC00 &amp;&amp; d &lt;= 0xDFFF) {<br />
        writer.append(d);<br />
        i++;<br />
       }<br />
      }<br />
     }</p>
<p>    } catch (Exception e) {<br />
     writer = new StringBuffer();<br />
     continue;<br />
    }</p>
<p>    String str = writer.toString();</p>
<p>    ByteArrayOutputStream baos = new ByteArrayOutputStream();<br />
    DataOutputStream dos = new DataOutputStream(baos);<br />
    try {<br />
     dos.writeUTF(str);<br />
     dos.flush();<br />
    } catch (Exception e) {<br />
     e.printStackTrace();<br />
    }</p>
<p>    byte[] temp = baos.toByteArray();<br />
    byte[] ba = new byte[temp.length - 2];<br />
    for (int ix = 0; ix &lt; ba.length; ix++) {<br />
     ba[ix] = temp[ix + 2];<br />
    }</p>
<p>    for (int j = 0; j &lt; ba.length; j++) {<br />
     out.append(’%&#8217;);</p>
<p>     char ch = forDigit((ba[j] &gt;&gt; 4) &amp; 0xF, 16);<br />
     out.append(ch);</p>
<p>     ch = forDigit(ba[j] &amp; 0xF, 16);<br />
     out.append(ch);<br />
    }</p>
<p>    writer = new StringBuffer();<br />
    try {<br />
     dos.close();<br />
     baos.close();<br />
    } catch (Exception e) {<br />
     e.printStackTrace();<br />
    }<br />
   }<br />
  }</p>
<p>  return out.toString();<br />
 }</p>
<p> private static char forDigit(int digit, int radix) {<br />
  if ((digit &gt;= radix) || (digit &lt; 0)) {<br />
   return ‘0′;<br />
  }<br />
  if (digit &lt; 10) {<br />
   return (char) (’0′ + digit);<br />
  }<br />
  return (char) (’A’ + digit &#8211; 10);<br />
 }<br />
}<br />
转：<a href="http://blog.csdn.net/hunhun1981/archive/2007/09/26/1801224.aspx">http://blog.csdn.net/hunhun1981/archive/2007/09/26/1801224.aspx</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/815/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>motionWelder动作编辑器封装使用</title>
		<link>http://www.javagg.com/archives/805</link>
		<comments>http://www.javagg.com/archives/805#comments</comments>
		<pubDate>Fri, 09 Jul 2010 08:12:11 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[动作编辑器]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=805</guid>
		<description><![CDATA[motionWelder是一位印度先生写的动作编辑器.曾经使用时向作者提出过一些BUG.人家都修改了.可谓是好心人啊.现在这软件也越来越强大了.
下面是我使用中的一些封装..
他有两种方式一种是MSimpleAnimationPlayer.另一种是implements MSprite.前一种是简单动画.后一种自己实现MSprite接口.可能扩展
比如MSimpleAnimationPlayer.我将成封装成Simple_Animation类
package pupaClan;
//简单动画类
import javax.microedition.lcdui.Graphics;
import mgo.common.Gamedata;
import com.studio.motionwelder.MSimpleAnimationPlayer;
import com.studio.motionwelder.MSpriteData;
import com.studio.motionwelder.MSpriteLoader;
public class Simple_Animation {
 public pupaClan_canvas canvas;
 public byte animation_Id;
 public final static byte loop_Once=-1;//一次
 public final static byte loop_While=0;//无限
 MSpriteData AnimationData=null;
    MSimpleAnimationPlayer  player=null;
    //构造方法
    public Simple_Animation(pupaClan_canvas canvas,String path,int animation_Id,int spriteX,int spriteY,boolean splitImageClips,int loopOffset){
  try {
   this.canvas=canvas;
   this.animation_Id=(byte) animation_Id;
   AnimationData=MSpriteLoader.loadMSprite(path,splitImageClips,ResourceLoader.getInstance());
   player = new MSimpleAnimationPlayer(AnimationData,spriteX,spriteY);
   player.setAnimation(this.animation_Id);
   player.setLoopOffset(loopOffset);
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
    [...]]]></description>
			<content:encoded><![CDATA[<p>motionWelder是一位印度先生写的动作编辑器.曾经使用时向作者提出过一些BUG.人家都修改了.可谓是好心人啊.现在这软件也越来越强大了.</p>
<p>下面是我使用中的一些封装..</p>
<p>他有两种方式一种是MSimpleAnimationPlayer.另一种是implements MSprite.前一种是简单动画.后一种自己实现MSprite接口.可能扩展<span id="more-805"></span></p>
<p>比如MSimpleAnimationPlayer.我将成封装成Simple_Animation类</p>
<p>package pupaClan;<br />
//简单动画类</p>
<p>import javax.microedition.lcdui.Graphics;</p>
<p>import mgo.common.Gamedata;</p>
<p>import com.studio.motionwelder.MSimpleAnimationPlayer;<br />
import com.studio.motionwelder.MSpriteData;<br />
import com.studio.motionwelder.MSpriteLoader;</p>
<p>public class Simple_Animation {<br />
 public pupaClan_canvas canvas;<br />
 public byte animation_Id;<br />
 public final static byte loop_Once=-1;//一次<br />
 public final static byte loop_While=0;//无限<br />
 MSpriteData AnimationData=null;<br />
    MSimpleAnimationPlayer  player=null;<br />
    //构造方法<br />
    public Simple_Animation(pupaClan_canvas canvas,String path,int animation_Id,int spriteX,int spriteY,boolean splitImageClips,int loopOffset){<br />
  try {<br />
   this.canvas=canvas;<br />
   this.animation_Id=(byte) animation_Id;<br />
   AnimationData=MSpriteLoader.loadMSprite(path,splitImageClips,ResourceLoader.getInstance());<br />
   player = new MSimpleAnimationPlayer(AnimationData,spriteX,spriteY);<br />
   player.setAnimation(this.animation_Id);<br />
   player.setLoopOffset(loopOffset);<br />
  } catch (Exception e) {<br />
   e.printStackTrace();<br />
  }<br />
 }<br />
    public void run(){//逻辑<br />
     player.update();<br />
    }<br />
    public int getAnimation(){//得到当前动画<br />
    return player.getAnimation();<br />
   }<br />
   public int getCurrentFrame(){//得到当前动画桢<br />
    return player.getCurrentFrame();<br />
   }<br />
    public boolean end(){//是否结束<br />
     return (player.getCurrentFrame()==(player.getFrameCount()-1));<br />
    }<br />
    public void paint(Graphics g){//绘制<br />
  g.setClip(0, 0, Gamedata.width, Gamedata.height);<br />
  player.drawFrame(g);<br />
 }<br />
}<br />
简单的动画就可以用他来生成一个.比如</p>
<p>startup_Flash=new Simple_Animation(this,&#8221;/anu/startup/pupastartup.anu&#8221;,0, 88, 190,false,Simple_Animation.loop_Once);</p>
<p>第一个参数是把CANVAS画布.第二个是用motionwelder生成的anu文件.第三个表示动画中的第几个(因为我的动画有好几个).第四,五个是坐标.第六个表示此动画要不要旋转.第7个是只播放一次.</p>
<p>第二种动画是implements MSprite实现的.</p>
<p>下面是我RPG游戏中一个实例</p>
<p>package pupaClan;<br />
//战斗怪类<br />
import javax.microedition.lcdui.Graphics;<br />
import com.studio.motionwelder.MPlayer;<br />
import com.studio.motionwelder.MSprite;<br />
import com.studio.motionwelder.MSpriteAnimationPlayer;<br />
import com.studio.motionwelder.MSpriteData;<br />
import com.studio.motionwelder.MSpriteLoader;<br />
import mgo.common.Gamedata;<br />
import mgo.common.Obj;<br />
import mgo.common.Timer;<br />
import mgo.common.Tools;<br />
import mgo.common.MediaPlayer;<br />
public class Monster extends Obj implements MSprite{<br />
 public pupaClan_canvas canvas;<br />
 /***Direction***/<br />
 public static final byte DIR_RIGHT = 0;<br />
 public static final byte DIR_LEFT = 1;<br />
 /** Sprite */<br />
 public  MPlayer player;<br />
 private MSpriteData spriteData;<br />
 public int hp,max_hp;<br />
 public int attack;<br />
 public int recovery;<br />
 public int exp;<br />
 public int coin;<br />
 public int level;<br />
 public String name;<br />
    //密锋动画初始化X偏移量<br />
 public final static int Bee_Animation_OPP_X=18;<br />
    //密锋动画初始化Y最大偏移量<br />
// public final static int Bee_Animation_MAX_OPP_Y=39;<br />
    //蜘蛛动画初始化X偏移量<br />
 public final static int Spider_Animation_OPP_X=14;<br />
    //蜘蛛动画初始化Y最大偏移量<br />
// public final static int Spider_Animation_MAX_OPP_Y=25;<br />
    //兔子动画初始化X偏移量<br />
 public final static int Coney_Animation_OPP_X=12;<br />
    //兔子动画初始化Y最大偏移量<br />
// public final static int Coney_Animation_MAX_OPP_Y=24;<br />
    //野鹿动画初始化X偏移量<br />
 public final static int Deer_Animation_OPP_X=14;<br />
    //野鹿动画初始化Y最大偏移量<br />
// public final static int Deer_Animation_MAX_OPP_Y=38;<br />
    //毒蜘蛛动画初始化X偏移量<br />
 public final static int ToxinSpider_Animation_OPP_X=21;<br />
    //毒蜘蛛动画初始化Y最大偏移量<br />
// public final static int ToxinSpider_Animation_MAX_OPP_Y=49;<br />
    //灰鹿动画初始化X偏移量<br />
 public final static int BlackDeer_Animation_OPP_X=16;<br />
    //灰鹿动画初始化Y最大偏移量<br />
// public final static int BlackDeer_Animation_MAX_OPP_Y=51;<br />
    //蛇动画初始化X偏移量<br />
 public final static int Snake_Animation_OPP_X=16;<br />
    //蛇动画初始化Y最大偏移量<br />
// public final static int Snake_Animation_MAX_OPP_Y=28;<br />
    //野狼动画初始化X偏移量<br />
 public final static int Wolf_Animation_OPP_X=23;<br />
    //野狼动画初始化Y最大偏移量<br />
// public final static int Wolf_Animation_MAX_OPP_Y=28;<br />
    //鹰动画初始化X偏移量<br />
// public final static int Eagle_Animation_OPP_X=14;<br />
    //鹰动画初始化Y最大偏移量<br />
// public final static int Eagle_Animation_MAX_OPP_Y=40;<br />
    //食人花初始化X偏移量<br />
 public final static int Flower_Animation_OPP_X=17;<br />
    //食人花初始化Y最大偏移量<br />
// public final static int Flower_Animation_MAX_OPP_Y=40;<br />
    //穿山甲初始化X偏移量<br />
 public final static int Pangolin_Animation_OPP_X=29;<br />
    //穿山甲初始化Y最大偏移量<br />
// public final static int Pangolin_Animation_MAX_OPP_Y=23;<br />
    //树怪初始化X偏移量<br />
   //public final static int TreeMonster_Animation_OPP_X=19;<br />
    //树怪初始化Y最大偏移量<br />
// public final static int TreeMonster_Animation_MAX_OPP_Y=38;<br />
    //雕初始化X偏移量<br />
 public final static int Vulture_Animation_OPP_X=25;<br />
    //雕初始化Y最大偏移量<br />
// public final static int Vulture_Animation_MAX_OPP_Y=54;<br />
    //霸王花初始化X偏移量<br />
 public final static int OverloadFlower_Animation_OPP_X=22;<br />
    //霸王花初始化Y最大偏移量<br />
// public final static int OverloadFlower_Animation_MAX_OPP_Y=45;<br />
    //眼镜蛇王初始化X偏移量<br />
 public final static int Cobra_Animation_OPP_X=21;<br />
    //眼镜蛇王初始化Y最大偏移量<br />
// public final static int Cobra_Animation_MAX_OPP_Y=34;<br />
    //千年树妖初始化X偏移量<br />
 //public final static int KiloTreeMonster_Animation_OPP_X=19;<br />
    //千年树妖初始化Y最大偏移量<br />
// public final static int KiloTreeMonster_Animation_MAX_OPP_Y=51;<br />
    //血狼初始化X偏移量<br />
 public final static int BloodWolf_Animation_OPP_X=25;<br />
    //血狼初始化Y最大偏移量<br />
// public final static int BloodWolf_Animation_MAX_OPP_Y=33;<br />
 <br />
    //人熊初始化X偏移量<br />
 public final static int Bear_Animation_OPP_X=27;<br />
    //人熊初始化Y最大偏移量<br />
// public final static int Bear_Animation_MAX_OPP_Y=65;<br />
    //大狼初始化X偏移量<br />
 public final static int BigWolf_Animation_OPP_X=17;<br />
    //大狼初始化Y最大偏移量<br />
// public final static int BigWolf_Animation_MAX_OPP_Y=48;<br />
    //剑齿虎初始化X偏移量<br />
 public final static int Tiger_Animation_OPP_X=43;<br />
    //剑齿虎初始化Y最大偏移量<br />
// public final static int Tiger_Animation_MAX_OPP_Y=51;<br />
    /** Animations */<br />
 public final static byte MON_SLEEP=0;//站着不动<br />
 public final static byte MON_KILL1=1;//普通攻击<br />
 public final static byte MON_INJURED1=2;//被攻击1,黄色闪光（小）<br />
 public final static byte MON_DIE=3;//死亡<br />
 public final static byte MON_KILL2=4;//非普通攻击,BOSS用<br />
 public final static byte MON_KILL3=5;//非普通攻击,BOSS大狼用<br />
 <br />
    private int animation;<br />
    public boolean 怪物操作;<br />
    public Timer timer=new Timer();<br />
    public Monster(pupaClan_canvas canvas,byte type,int spriteX,int spriteY){<br />
  try{<br />
   this.canvas=canvas;<br />
   this.type=type;<br />
   String path = null;<br />
   int Animation_OPP_X = 0;<br />
   switch(this.type){<br />
       case 蜜蜂:<br />
        setLevel(Tools.getRand(1,3));<br />
        Animation_OPP_X=Bee_Animation_OPP_X;<br />
         path=&#8221;/anu/monster/Bee.anu&#8221;;<br />
         name=&#8221;蜜蜂&#8221;;<br />
    break;<br />
       case 蜘蛛:<br />
        setLevel(Tools.getRand(1,3));<br />
        Animation_OPP_X=Spider_Animation_OPP_X;<br />
        path=&#8221;/anu/monster/Spider.anu&#8221;;<br />
        name=&#8221;蜘蛛&#8221;;<br />
       break;<br />
       case 兔子:<br />
        setLevel(Tools.getRand(3,7));<br />
        Animation_OPP_X=Coney_Animation_OPP_X;<br />
        path=&#8221;/anu/monster/Coney.anu&#8221;;<br />
        name=&#8221;兔子&#8221;;<br />
       break;<br />
       case 野鹿:<br />
        setLevel(Tools.getRand(5,10));<br />
        Animation_OPP_X=Deer_Animation_OPP_X;<br />
        path=&#8221;/anu/monster/Deer.anu&#8221;;<br />
        name=&#8221;野鹿&#8221;;<br />
       break;<br />
       case 灰兔:<br />
        setLevel(Tools.getRand(10,13));<br />
        Animation_OPP_X=Coney_Animation_OPP_X;<br />
        path=&#8221;/anu/monster/hui-Coney.anu&#8221;;<br />
        name=&#8221;灰兔&#8221;;<br />
       break;<br />
       case 毒蜘蛛:<br />
        setLevel(Tools.getRand(11,15));<br />
        Animation_OPP_X=ToxinSpider_Animation_OPP_X;<br />
        path=&#8221;/anu/monster/ToxinSpider.anu&#8221;;<br />
        name=&#8221;毒蜘蛛&#8221;;<br />
       break;<br />
       case 蜂王:<br />
        setLevel(Tools.getRand(15,20));<br />
        Animation_OPP_X=Bee_Animation_OPP_X;<br />
         path=&#8221;/anu/monster/king-Bee.anu&#8221;;<br />
         name=&#8221;蜂王&#8221;;<br />
       break;<br />
       case 灰鹿:<br />
        setLevel(Tools.getRand(18,22));<br />
        Animation_OPP_X=BlackDeer_Animation_OPP_X;<br />
         path=&#8221;/anu/monster/BlackDeer.anu&#8221;;<br />
         name=&#8221;灰鹿&#8221;;<br />
       break;<br />
       case 蛇:<br />
        setLevel(Tools.getRand(20,25));<br />
        Animation_OPP_X=Snake_Animation_OPP_X;<br />
         path=&#8221;/anu/monster/Snake.anu&#8221;;<br />
         name=&#8221;蛇&#8221;;<br />
       break;<br />
       case 野狼:<br />
        setLevel(Tools.getRand(22,25));<br />
        Animation_OPP_X=Wolf_Animation_OPP_X;<br />
         path=&#8221;/anu/monster/Wolf.anu&#8221;;<br />
         name=&#8221;野狼&#8221;;<br />
       break;<br />
       case 青狼:<br />
        setLevel(Tools.getRand(38,40));<br />
        Animation_OPP_X=Wolf_Animation_OPP_X;<br />
         path=&#8221;/anu/monster/Wolf1.anu&#8221;;<br />
         name=&#8221;青狼&#8221;;<br />
       break;<br />
       case 黑鹿:<br />
        setLevel(Tools.getRand(25,28));<br />
           Animation_OPP_X=BlackDeer_Animation_OPP_X;<br />
            path=&#8221;/anu/monster/HaDeer.anu&#8221;;<br />
            name=&#8221;黑鹿&#8221;;<br />
          break;<br />
       case 食人花:<br />
        setLevel(Tools.getRand(28,32));<br />
           Animation_OPP_X=Flower_Animation_OPP_X;<br />
            path=&#8221;/anu/monster/Flower.anu&#8221;;<br />
            name=&#8221;食人花&#8221;;<br />
          break;<br />
       case 穿山甲:<br />
        setLevel(Tools.getRand(30,35));<br />
           Animation_OPP_X=Pangolin_Animation_OPP_X;<br />
            path=&#8221;/anu/monster/Pangolin.anu&#8221;;<br />
            name=&#8221;穿山甲&#8221;;<br />
       break;<br />
       case 穿山甲王:<br />
        setLevel(Tools.getRand(43,46));<br />
           Animation_OPP_X=Pangolin_Animation_OPP_X;<br />
            path=&#8221;/anu/monster/Pangolin1.anu&#8221;;<br />
            name=&#8221;穿山甲王&#8221;;<br />
       break;<br />
       case 雕:<br />
        setLevel(Tools.getRand(35,40));<br />
           Animation_OPP_X=Vulture_Animation_OPP_X;<br />
            path=&#8221;/anu/monster/Vulture.anu&#8221;;<br />
            name=&#8221;雕&#8221;;<br />
       break;<br />
       case 霸王花:<br />
        setLevel(Tools.getRand(40,45));<br />
              Animation_OPP_X=OverloadFlower_Animation_OPP_X;<br />
               path=&#8221;/anu/monster/OverloadFlower.anu&#8221;;<br />
               name=&#8221;霸王花&#8221;;<br />
          break;<br />
       case 眼镜蛇王:<br />
        setLevel(Tools.getRand(42,47));<br />
              Animation_OPP_X=Cobra_Animation_OPP_X;<br />
               path=&#8221;/anu/monster/Cobra.anu&#8221;;<br />
               name=&#8221;眼镜蛇王&#8221;;<br />
          break;<br />
       case 血狼:<br />
        setLevel(Tools.getRand(45,50));<br />
                 Animation_OPP_X=BloodWolf_Animation_OPP_X;<br />
                  path=&#8221;/anu/monster/BloodWolf.anu&#8221;;<br />
                  name=&#8221;血狼&#8221;;<br />
             break;<br />
       case 人熊:<br />
        hp=max_hp=480;attack=95;recovery=50;exp=632;coin=500;<br />
                 Animation_OPP_X=Bear_Animation_OPP_X;<br />
                  path=&#8221;/anu/monster/Bear.anu&#8221;;<br />
                  name=&#8221;人熊&#8221;;<br />
             break;<br />
       case 大狼:<br />
        hp=max_hp=850;attack=208;recovery=108;exp=2571;coin=1280;<br />
                 Animation_OPP_X=BigWolf_Animation_OPP_X;<br />
                  path=&#8221;/anu/monster/BigWolf.anu&#8221;;<br />
                  name=&#8221;大狼&#8221;;<br />
             break;<br />
       case 剑齿虎:<br />
        hp=max_hp=1120;attack=309;recovery=160;exp=4720;coin=2000;<br />
                 Animation_OPP_X=Tiger_Animation_OPP_X;<br />
                  path=&#8221;/anu/monster/Tiger.anu&#8221;;<br />
                  name=&#8221;剑齿虎&#8221;;<br />
             break;<br />
   }<br />
   this.spriteX=Animation_OPP_X+spriteX;<br />
   this.spriteY=spriteY;<br />
   spriteData=MSpriteLoader.loadMSprite(path,false,ResourceLoader.getInstance());<br />
   player = new MSpriteAnimationPlayer(spriteData,this);<br />
   setAnimation(MON_SLEEP);<br />
   direction = DIR_RIGHT;<br />
  }catch (Exception e){<br />
   e.printStackTrace();<br />
  }<br />
 }<br />
 public void run(){<br />
  if(Obj.isMonsterBoss(this.type)){//BOSS<br />
   switch(this.type){<br />
       case Obj.人熊:<br />
       case Obj.剑齿虎:<br />
        switch (animation) {<br />
         case MON_SLEEP:<br />
          if(canvas.battle_hero.主角操作完成 &amp; timer.arrive_Time(canvas.battle_hero.延迟时间)){<br />
           if(hp&lt;(max_hp&gt;&gt;1)){//自身生命少于一半<br />
               setAnimation(Tools.getOnlyRand(MON_KILL1, MON_KILL2));<br />
              }else{<br />
               setAnimation(MON_KILL1);<br />
              }<br />
          }<br />
         break;<br />
            case MON_KILL1:<br />
             if(!timer.arrive_Time(canvas.battle_hero.延迟时间))return;<br />
             if(getCurrentFrame()==5)canvas.battle_hero.setAnimation(BattleHero.HERO_INJURED1);<br />
            break;<br />
            case MON_KILL2:<br />
             if(!timer.arrive_Time(canvas.battle_hero.延迟时间))return;<br />
             if(getCurrentFrame()==6)canvas.battle_hero.setAnimation(BattleHero.HERO_INJURED1);<br />
            break;<br />
        }<br />
    break;<br />
       case Obj.大狼:<br />
        switch (animation) {<br />
         case MON_SLEEP:<br />
          if(canvas.battle_hero.主角操作完成 &amp; timer.arrive_Time(canvas.battle_hero.延迟时间)){<br />
           if(hp&lt;(max_hp&gt;&gt;1)){//自身生命少于一半<br />
               setAnimation(Tools.getOnlyRand(MON_KILL1, MON_KILL2, MON_KILL3));<br />
              }else{<br />
               setAnimation(MON_KILL1);<br />
              }<br />
          }<br />
         break;<br />
            case MON_KILL1:<br />
             if(!timer.arrive_Time(canvas.battle_hero.延迟时间))return;<br />
             if(getCurrentFrame()==5)canvas.battle_hero.setAnimation(BattleHero.HERO_INJURED1);<br />
            break;<br />
            case MON_KILL2:<br />
            case MON_KILL3:<br />
             if(!timer.arrive_Time(canvas.battle_hero.延迟时间))return;<br />
             if(getCurrentFrame()==5)canvas.battle_hero.setAnimation(BattleHero.HERO_INJURED1);<br />
            break;<br />
        }<br />
    break;<br />
   }<br />
  }else{//小怪<br />
   switch (animation){<br />
       case MON_SLEEP:<br />
        if(canvas.battle_hero.主角操作完成 &amp; timer.arrive_Time(canvas.battle_hero.延迟时间))setAnimation(MON_KILL1);<br />
       break;<br />
          case MON_KILL1:<br />
           if(!timer.arrive_Time(canvas.battle_hero.延迟时间))return;<br />
           if(getCurrentFrame()==4)canvas.battle_hero.setAnimation(BattleHero.HERO_INJURED1);<br />
          break;<br />
      }<br />
  }<br />
  player.update();<br />
  }<br />
 public void endOfAnimation(){<br />
        switch (animation){<br />
              case MON_KILL1:<br />
              case MON_KILL2:<br />
              case MON_KILL3:<br />
               setAnimation(MON_SLEEP);<br />
               canvas.battle_hero.主角操作完成=false;<br />
           break;<br />
        case MON_INJURED1://普通攻击<br />
         check_Die(canvas.common_hero.attack+(canvas.返回主角身上装备(Equip.攻击装备)!=null?((Equip)canvas.返回主角身上装备(Equip.攻击装备)).getAttack():0)-recovery);<br />
        break;<br />
        case MON_DIE:<br />
         if(!canvas.battle_Complete){<br />
           canvas.mediaPlayer.playSound(&#8220;/sound/battlesuccess.mid&#8221;, MediaPlayer.play_Once);//播放音乐<br />
          checkTaskFromBattle();//更新任务<br />
          /****增加主角经验,金币,检测主角是否升级****/<br />
          canvas.common_hero.coin=canvas.common_hero.coin+coin;<br />
          canvas.common_hero.exp=canvas.common_hero.exp+exp;<br />
          canvas.hero_IsUpgrade=canvas.common_hero.checkLevel();<br />
          canvas.battle_Complete=true;<br />
          canvas.cursor_y=0;<br />
          canvas.backup_time=System.currentTimeMillis();<br />
          canvas.timer.init_Time();<br />
         }<br />
        break; <br />
  }<br />
  }<br />
 private void check_Die(int injure){//根据injure值检测怪物是否死亡<br />
  if(injure&lt;0)injure=0;<br />
        hp=hp-injure;<br />
        if(hp&lt;0)hp=0;<br />
        if(hp&gt;0){//怪没有死<br />
         if(Obj.isMonsterBoss(this.type)){//BOSS<br />
       switch(this.type){<br />
           case Obj.人熊:<br />
           case Obj.剑齿虎:<br />
            if(hp&lt;(max_hp&gt;&gt;1)){//自身生命少于一半<br />
             setAnimation(Tools.getOnlyRand(MON_KILL1, MON_KILL2));<br />
            }else{<br />
             setAnimation(MON_KILL1);<br />
            }<br />
            canvas.主角操作完毕并设置延迟时间(700l);<br />
        break;<br />
           case Obj.大狼:<br />
            if(hp&lt;(max_hp&gt;&gt;1)){//自身生命少于一半<br />
             setAnimation(Tools.getOnlyRand(MON_KILL1, MON_KILL2, MON_KILL3));<br />
            }else{<br />
             setAnimation(MON_KILL1);<br />
            }<br />
            canvas.主角操作完毕并设置延迟时间(700l);<br />
           break;<br />
       }<br />
      }else{//小怪<br />
       setAnimation(MON_KILL1);<br />
       canvas.主角操作完毕并设置延迟时间(700l);<br />
      }<br />
     }else setAnimation(MON_DIE);//怪死亡了<br />
    }<br />
 public void paint(Graphics g){//绘制<br />
  g.setClip(0, 0, Gamedata.width, Gamedata.height);<br />
  player.drawFrame(g);<br />
 }<br />
 public int getSpriteDrawX(){<br />
  return getSpriteX();<br />
 }<br />
 <br />
 public int getSpriteDrawY(){<br />
  return getSpriteY();<br />
 }<br />
    byte orientation;<br />
 public byte getSpriteOrientation(){<br />
  return (byte)direction;<br />
 }<br />
 public void updateSpritePosition(int incX,int incY){<br />
  spriteX+=incX;<br />
  spriteY+=incY;</p>
<p> }<br />
  public boolean end(){<br />
     return (player.getCurrentFrame()==(player.getFrameCount()-1));<br />
  }<br />
 public int getAnimation(){<br />
  return player.getAnimation();<br />
 }<br />
 public int getCurrentFrame(){<br />
  return player.getCurrentFrame();<br />
 }<br />
 public void setAnimation(int animation){<br />
   switch (animation) {<br />
      case MON_SLEEP:<br />
      player.setAnimation(MON_SLEEP);<br />
      player.setLoopOffset(0);<br />
   break;<br />
      default:<br />
       player.setAnimation(animation);<br />
      player.setLoopOffset(-1);<br />
      break;<br />
      }<br />
         this.animation = animation; <br />
 }<br />
  public void setLevel(int level){//设置怪物级别<br />
  this.level=level;<br />
  switch(this.level){<br />
      case 1:<br />
       hp=max_hp=20;attack=5;recovery=2;exp=Tools.getRand(8,10);coin=Tools.getRand(1,10);<br />
   break;<br />
      case 2:<br />
       hp=max_hp=23;attack=6;recovery=3;exp=Tools.getRand(8,10);coin=Tools.getRand(1,10);<br />
   break;<br />
      case 3:<br />
       hp=max_hp=26;attack=8;recovery=4;exp=Tools.getRand(8,10);coin=Tools.getRand(1,10);<br />
   break;<br />
      case 4:<br />
       hp=max_hp=30;attack=9;recovery=4;exp=Tools.getRand(8,10);coin=Tools.getRand(1,10);<br />
   break;<br />
      case 5:<br />
       hp=max_hp=34;attack=11;recovery=5;exp=Tools.getRand(8,10);coin=Tools.getRand(1,10);<br />
   break;<br />
      case 6:<br />
       hp=max_hp=39;attack=13;recovery=6;exp=Tools.getRand(34,40);coin=Tools.getRand(14,40);<br />
   break;<br />
      case 7:<br />
       hp=max_hp=44;attack=15;recovery=7;exp=Tools.getRand(34,40);coin=Tools.getRand(14,40);<br />
   break;<br />
      case 8:<br />
       hp=max_hp=50;attack=18;recovery=9;exp=Tools.getRand(34,40);coin=Tools.getRand(14,40);<br />
   break;<br />
      case 9:<br />
       hp=max_hp=56;attack=20;recovery=10;exp=Tools.getRand(34,40);coin=Tools.getRand(14,40);<br />
   break;<br />
      case 10:<br />
       hp=max_hp=63;attack=23;recovery=11;exp=Tools.getRand(34,40);coin=Tools.getRand(14,40);<br />
   break;<br />
      case 11:<br />
       hp=max_hp=70;attack=26;recovery=13;exp=Tools.getRand(94,110);coin=Tools.getRand(48,90);<br />
   break;<br />
      case 12:<br />
       hp=max_hp=78;attack=29;recovery=14;exp=Tools.getRand(94,110);coin=Tools.getRand(48,90);<br />
   break;<br />
      case 13:<br />
       hp=max_hp=86;attack=32;recovery=16;exp=Tools.getRand(94,110);coin=Tools.getRand(48,90);<br />
   break;<br />
      case 14:<br />
       hp=max_hp=95;attack=36;recovery=18;exp=Tools.getRand(94,110);coin=Tools.getRand(48,90);<br />
   break;<br />
      case 15:<br />
       hp=max_hp=104;attack=40;recovery=20;exp=Tools.getRand(94,110);coin=Tools.getRand(48,90);<br />
   break;<br />
      case 16:<br />
       hp=max_hp=113;attack=44;recovery=22;exp=Tools.getRand(171,200);coin=Tools.getRand(102,160);<br />
   break;<br />
      case 17:<br />
       hp=max_hp=123;attack=48;recovery=24;exp=Tools.getRand(171,200);coin=Tools.getRand(102,160);<br />
   break;<br />
      case 18:<br />
       hp=max_hp=134;attack=52;recovery=26;exp=Tools.getRand(171,200);coin=Tools.getRand(102,160);<br />
   break;<br />
      case 19:<br />
       hp=max_hp=144;attack=57;recovery=28;exp=Tools.getRand(171,200);coin=Tools.getRand(102,160);<br />
   break;<br />
      case 20:<br />
       hp=max_hp=156;attack=62;recovery=31;exp=Tools.getRand(171,200);coin=Tools.getRand(102,160);<br />
   break;<br />
  <br />
      case 21:<br />
       hp=max_hp=168;attack=67;recovery=33;exp=Tools.getRand(300,350);coin=Tools.getRand(176,250);<br />
   break;<br />
      case 22:<br />
       hp=max_hp=180;attack=72;recovery=36;exp=Tools.getRand(300,350);coin=Tools.getRand(176,250);<br />
   break;<br />
      case 23:<br />
       hp=max_hp=193;attack=77;recovery=38;exp=Tools.getRand(300,350);coin=Tools.getRand(176,250);<br />
   break;<br />
      case 24:<br />
       hp=max_hp=206;attack=83;recovery=41;exp=Tools.getRand(300,350);coin=Tools.getRand(176,250);<br />
   break;<br />
      case 25:<br />
       hp=max_hp=220;attack=89;recovery=44;exp=Tools.getRand(300,350);coin=Tools.getRand(176,250);<br />
   break;<br />
      case 26:<br />
       hp=max_hp=234;attack=95;recovery=47;exp=Tools.getRand(462,540);coin=Tools.getRand(270,360);<br />
   break;<br />
      case 27:<br />
       hp=max_hp=248;attack=101;recovery=50;exp=Tools.getRand(462,540);coin=Tools.getRand(270,360);<br />
   break;<br />
      case 28:<br />
       hp=max_hp=263;attack=107;recovery=53;exp=Tools.getRand(462,540);coin=Tools.getRand(270,360);<br />
   break;<br />
      case 29:<br />
       hp=max_hp=279;attack=114;recovery=57;exp=Tools.getRand(462,540);coin=Tools.getRand(270,360);<br />
   break;<br />
      case 30:<br />
       hp=max_hp=295;attack=120;recovery=60;exp=Tools.getRand(462,540);coin=Tools.getRand(270,360);<br />
   break;<br />
      case 31:<br />
       hp=max_hp=311;attack=127;recovery=63;exp=Tools.getRand(651,760);coin=Tools.getRand(384,490);<br />
   break;<br />
      case 32:<br />
       hp=max_hp=328;attack=135;recovery=67;exp=Tools.getRand(651,760);coin=Tools.getRand(384,490);<br />
   break;<br />
      case 33:<br />
       hp=max_hp=346;attack=142;recovery=71;exp=Tools.getRand(651,760);coin=Tools.getRand(384,490);<br />
   break;<br />
      case 34:<br />
       hp=max_hp=363;attack=149;recovery=74;exp=Tools.getRand(651,760);coin=Tools.getRand(384,490);<br />
   break;<br />
      case 35:<br />
       hp=max_hp=382;attack=157;recovery=78;exp=Tools.getRand(651,760);coin=Tools.getRand(384,490);<br />
   break;<br />
      case 36:<br />
       hp=max_hp=401;attack=165;recovery=82;exp=Tools.getRand(857,1000);coin=Tools.getRand(518,640);<br />
   break;<br />
      case 37:<br />
       hp=max_hp=420;attack=173;recovery=86;exp=Tools.getRand(857,1000);coin=Tools.getRand(518,640);<br />
   break;<br />
      case 38:<br />
       hp=max_hp=440;attack=182;recovery=91;exp=Tools.getRand(857,1000);coin=Tools.getRand(518,640);<br />
   break;<br />
      case 39:<br />
       hp=max_hp=460;attack=190;recovery=95;exp=Tools.getRand(857,1000);coin=Tools.getRand(518,640);<br />
   break;<br />
      case 40:<br />
       hp=max_hp=480;attack=199;recovery=99;exp=Tools.getRand(857,1000);coin=Tools.getRand(518,640);<br />
   break;<br />
      case 41:<br />
       hp=max_hp=501;attack=208;recovery=104;exp=Tools.getRand(1114,1300);coin=Tools.getRand(672,810);<br />
   break;<br />
      case 42:<br />
       hp=max_hp=523;attack=217;recovery=108;exp=Tools.getRand(1114,1300);coin=Tools.getRand(672,810);<br />
   break;<br />
      case 43:<br />
       hp=max_hp=545;attack=227;recovery=113;exp=Tools.getRand(11114,1300);coin=Tools.getRand(672,810);<br />
   break;<br />
      case 44:<br />
       hp=max_hp=567;attack=236;recovery=118;exp=Tools.getRand(11114,1300);coin=Tools.getRand(672,810);<br />
   break;<br />
      case 45:<br />
       hp=max_hp=590;attack=246;recovery=123;exp=Tools.getRand(11114,1300);coin=Tools.getRand(672,810);<br />
   break;<br />
      case 46:<br />
       hp=max_hp=614;attack=256;recovery=128;exp=Tools.getRand(1285,1500);coin=Tools.getRand(846,1000);<br />
   break;<br />
      case 47:<br />
       hp=max_hp=638;attack=266;recovery=133;exp=Tools.getRand(1285,1500);coin=Tools.getRand(846,1000);<br />
   break;<br />
      case 48:<br />
       hp=max_hp=662;attack=276;recovery=138;exp=Tools.getRand(1285,1500);coin=Tools.getRand(846,1000);<br />
   break;<br />
      case 49:<br />
       hp=max_hp=687;attack=287;recovery=143;exp=Tools.getRand(1285,1500);coin=Tools.getRand(846,1000);<br />
   break;<br />
      case 50:<br />
       hp=max_hp=712;attack=298;recovery=149;exp=Tools.getRand(1285,1500);coin=Tools.getRand(846,1000);<br />
   break;<br />
     }<br />
 }<br />
 public void checkTaskFromBattle(){//战斗胜利,更新任务中各个数量<br />
   for(int i=0;i&lt;canvas.taskVector.size();i++){<br />
    Task t=(Task) canvas.taskVector.elementAt(i);<br />
    if(t.task_Name.equals(Task.task_Name5)&amp;this.type==Obj.蜜蜂){<br />
     if(canvas.common_hero.杀死蜜蜂数量&lt;20)canvas.common_hero.杀死蜜蜂数量++;<br />
     break;<br />
    }<br />
    if(t.task_Name.equals(Task.task_Name6)&amp;this.type==Obj.毒蜘蛛){<br />
     if(canvas.common_hero.杀死毒蜘蛛数量&lt;30)canvas.common_hero.杀死毒蜘蛛数量++;<br />
     break;<br />
    }<br />
    if(t.task_Name.equals(Task.task_Name7)&amp;this.type==Obj.食人花){<br />
     if(canvas.common_hero.杀死食人花数量&lt;30)canvas.common_hero.杀死食人花数量++;<br />
     break;<br />
    }<br />
    if(t.task_Name.equals(Task.task_Name8)){<br />
     switch(this.type){<br />
         case Obj.霸王花:<br />
          if(canvas.common_hero.杀死霸王花数量&lt;10)canvas.common_hero.杀死霸王花数量++;<br />
      break;<br />
         case Obj.眼镜蛇王:<br />
          if(canvas.common_hero.杀死眼镜蛇王数量&lt;10)canvas.common_hero.杀死眼镜蛇王数量++;<br />
         break;<br />
         case Obj.穿山甲王:<br />
          if(canvas.common_hero.杀死穿山甲王数量&lt;10)canvas.common_hero.杀死穿山甲王数量++;<br />
         break;<br />
         case Obj.血狼:<br />
          if(canvas.common_hero.杀死血狼数量&lt;10)canvas.common_hero.杀死血狼数量++;<br />
         break;<br />
     }<br />
     break;<br />
    }<br />
   }<br />
 }<br />
}</p>
<p>此类是怪的行为类.</p>
<p>endOfAnimation()在一个动画结束时会调用.</p>
<p>updateSpritePosition()是更新坐标.检测</p>
<p>getSpriteOrientation()得到方向</p>
<p>setAnimation()设置新的动画</p>
<p>end()检查是否播放结束</p>
<p>getSpriteDrawX()得到绘制X.</p>
<p>getSpriteDrawY()得到绘制Y.</p>
<p>无论用哪种方式.都要自己实现ResourceLoader类</p>
<p>ResourceLoader类就是你的动画需要指定创建哪些图片资源</p>
<p>有loadImage和loadImageClip二种方法</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/805/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>手机游戏动作编辑器MotionWelder&#8211;编写程序</title>
		<link>http://www.javagg.com/archives/800</link>
		<comments>http://www.javagg.com/archives/800#comments</comments>
		<pubDate>Thu, 08 Jul 2010 06:49:01 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[游戏]]></category>
		<category><![CDATA[动作编辑器]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=800</guid>
		<description><![CDATA[开发环境：Eclipse+EclipseMe （Eclipse3.4版本以上使用EclipseMe时在添加第三方库常常会出现classnotfound异常，可使用mtj代替EclipseME，或使用低一些的Eclipse版本）
1、新建J2ME工程，导入MotionWelder的J2ME库（在该程序下载包里J2ME 的lib目录里的motionwelder.jar）
       右键工程&#8211;&#62;Build Path &#8211;&#62;Add external archives&#8230; &#8212;&#62;选择motionwelder.jar打开，即可导入完毕。
2、把导出的动作数据文件拷到工程的资源目录，导入动作数据文件
/*
spriteName 动作数据文件
splitImageClips 内存加载图片的方式，如果为false则加载完整的图片（图片没有切片），true则加载切片的图片
imageloader  加载动作所需图片的类
*/
MSpriteData animationData = MSpriteLoader.loadMSprite(java.lang.String spriteName, boolean splitImageClips, MSpriteImageLoader imageloader)
3、加载动作图片
interface MSpriteImageLoader：
splitImageClips = false  - 加载完整的图片
           Image[]  loadImage(spriteName,imageId,orientationUsedInStudio);
splitImageClips = true &#8211; 加载图片切片
          Image[] loadImageClip(String spriteName,int imageId,int x,int y,int w,int h,int orientationUsedInStudio);
-spriteName
         &#8211; 动作数据文件的名字
-orientationUsedInStudio
        -使用了的翻转类型,
               MSprite.ORIENTATION_NONE                         &#8211; 无翻转
               MSprite.ORIENTATION_FLIP_H                      - 水平翻转
               MSprite.ORIENTATION_FLIP_V                      - 垂直翻转
               MSprite.ORIENTATION_FLIP_BOTH_H_V   &#8211; 水平和垂直翻转
- imageId
         &#8211; 图片id，即动作所使用到的图片
-x,y,w,h      
       -切片在图片中的坐标（x，y，宽，高）.
Image[3]
       Image[0] =无翻转图片
       Image[1] [...]]]></description>
			<content:encoded><![CDATA[<p>开发环境：Eclipse+EclipseMe （Eclipse3.4版本以上使用EclipseMe时在添加第三方库常常会出现classnotfound异常，可使用mtj代替EclipseME，或使用低一些的Eclipse版本）<br />
1、新建J2ME工程，导入MotionWelder的J2ME库（在该程序下载包里J2ME 的lib目录里的motionwelder.jar）<br />
       右键工程&#8211;&gt;Build Path &#8211;&gt;Add external archives&#8230; &#8212;&gt;选择motionwelder.jar打开，即可导入完毕。<br />
2、把导出的动作数据文件拷到工程的资源目录，导入动作数据文件<br />
/*<br />
spriteName 动作数据文件<br />
splitImageClips 内存加载图片的方式，如果为false则加载完整的图片（图片没有切片），true则加载切片的图片<br />
imageloader  加载动作所需图片的类<br />
*/<br />
MSpriteData animationData = MSpriteLoader.loadMSprite(java.lang.String spriteName, boolean splitImageClips, MSpriteImageLoader imageloader)<br />
3、加载动作图片<br />
interface MSpriteImageLoader：<br />
splitImageClips = false  - 加载完整的图片<br />
           Image[]  loadImage(spriteName,imageId,orientationUsedInStudio);<span id="more-800"></span></p>
<p>splitImageClips = true &#8211; 加载图片切片<br />
          Image[] loadImageClip(String spriteName,int imageId,int x,int y,int w,int h,int orientationUsedInStudio);</p>
<p>-spriteName<br />
         &#8211; 动作数据文件的名字<br />
-orientationUsedInStudio<br />
        -使用了的翻转类型,<br />
               MSprite.ORIENTATION_NONE                         &#8211; 无翻转<br />
               MSprite.ORIENTATION_FLIP_H                      - 水平翻转<br />
               MSprite.ORIENTATION_FLIP_V                      - 垂直翻转<br />
               MSprite.ORIENTATION_FLIP_BOTH_H_V   &#8211; 水平和垂直翻转<br />
- imageId<br />
         &#8211; 图片id，即动作所使用到的图片<br />
-x,y,w,h      <br />
       -切片在图片中的坐标（x，y，宽，高）.<br />
Image[3]<br />
       Image[0] =无翻转图片<br />
       Image[1] = 水平翻转图片      // 如果没有为null<br />
       Image[2] = 垂直翻转图片         // 如果没有为null<br />
4、播放动作<br />
/*动作列表*/<br />
public static int ANIM_STAND = 0;<br />
public static int ANIM_RUN = 1;</p>
<p>/* 创建动作播放器 */<br />
MSimpleAnimationPlayer player = new MSimpleAnimationPlayer(MSpriteData spriteData, int spriteX, int spriteY);<br />
或<br />
MSpriteAnimationPlayer player = new MSpriteAnimationPlayer(MSpriteData spriteData, MSprite sprite);<br />
两个的区别在于：正如名字一样MSpriteAnimationPlayer提供的一个简单的播放器，它在处理end of animation时是仅停止播放，不能更好地拓展。如果需要灵巧地控制各个动画的切换最好使用MSpriteAnimationPlayer。</p>
<p>/*设置当前的播放动作*/<br />
player.setAnimation(ANIM_STAND);<br />
player.setLoopOffset(-1);           // 播放一次..<br />
player.setLoopOffset(0);            // 从第一帧到帧尾循环播放<br />
player.setLoopOffset(2);           // 从第二帧到帧尾循环播放</p>
<p>/* 循环调用这里，更新和绘制动作*/<br />
player.update();<br />
player.drawFrame(g);</p>
<p>例子：使用第一节的数据文件，当我们按数字键5或者中键的时候施放这个向下攻击的动作。主要代码如下：<br />
主屏幕   GameScreen.java<br />
import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Graphics;<br />
public class GameScreen extends Canvas implements Runnable {<br />
private GameSprite gameSprite;//游戏精灵<br />
private static final int KEY_FIRE=-5;//键盘中键<br />
public static boolean isHit = false;//是否发动攻击<br />
public GameScreen() {<br />
  gameSprite = new GameSprite();//实例化游戏精灵<br />
  Thread t = new Thread(this);//创建线程<br />
  t.start();//启动线程<br />
}<br />
protected void paint(Graphics g) {<br />
  g.setColor(0xffffffff);<br />
  g.fillRect(0, 0, getWidth(), getHeight());//清屏<br />
  gameSprite.paint(g);//绘制精灵<br />
}<br />
public void run() {<br />
  try {<br />
   long time;<br />
   while (true) {<br />
    time = System.currentTimeMillis();<br />
    //重绘<br />
    repaint();<br />
    serviceRepaints();<br />
    if (isHit) {//如果发动攻击<br />
     gameSprite.update();//更新精灵<br />
    }<br />
    long timeTakenForPainting = System.currentTimeMillis() &#8211; time;<br />
    if (timeTakenForPainting &lt; 100) {<br />
     Thread.sleep(100 &#8211; timeTakenForPainting);<br />
    }<br />
   }<br />
  } catch (Exception e) {<br />
   System.out.println(&#8220;Error &#8221; + e);<br />
  }<br />
}<br />
protected void keyPressed(int key) {<br />
  if (key == Canvas.KEY_NUM5 || key == KEY_FIRE) {<br />
   isHit = true;//按数字键5或中键攻击<br />
  }<br />
}<br />
protected void keyReleased(int key) {<br />
}<br />
}</p>
<p>游戏精灵  GameSprite.java<br />
import javax.microedition.lcdui.Graphics;<br />
import com.studio.motionwelder.MPlayer;<br />
import com.studio.motionwelder.MSprite;<br />
import com.studio.motionwelder.MSpriteAnimationPlayer;<br />
import com.studio.motionwelder.MSpriteData;<br />
import com.studio.motionwelder.MSpriteLoader;<br />
public class GameSprite implements MSprite {<br />
private MSpriteData spriteData;<br />
private MPlayer player;<br />
private int animation;<br />
private static final int DOWN_HIT = 0;<br />
int spriteX = 100;//精灵坐标<br />
int spriteY = 175;<br />
public GameSprite() {<br />
  try {<br />
   loadResource();//加载资源<br />
  } catch (Exception e) {<br />
   e.printStackTrace();<br />
  }<br />
  player = new MSpriteAnimationPlayer(spriteData, this);//创建播放器<br />
  this.setAnimation(DOWN_HIT);//设置当前动画ID<br />
}<br />
private void setAnimation(int animation) {//设置动画ID<br />
  switch (animation) {<br />
  case DOWN_HIT:<br />
   player.setAnimation(DOWN_HIT);<br />
   break;<br />
  }<br />
  this.animation = animation;<br />
}<br />
private void loadResource() throws Exception {<br />
  spriteData = MSpriteLoader.loadMSprite(&#8220;/SwordSprite.anu&#8221;, true,<br />
    ResourceLoader.getInstance());//加载数据文件<br />
}<br />
public void update() {<br />
  switch (animation) {<br />
  case DOWN_HIT:<br />
   player.setLoopOffset(-1);//设置仅播放一次<br />
   break;<br />
  }<br />
  player.update();//下一帧<br />
}<br />
public void endOfAnimation() {//处理动画播放完后的方法，可以添加切换到另外的动画等等<br />
  switch (animation) {<br />
  case DOWN_HIT:<br />
   player.setFrame(0);//如果播放完则设置帧为第0帧<br />
   break;<br />
  }<br />
  GameScreen.isHit = false;//攻击动作完成<br />
}<br />
public int getSpriteDrawX() {//设置精灵的绘制坐标X<br />
  return spriteX;<br />
}<br />
public int getSpriteDrawY() {//设置精灵的绘制坐标Y<br />
  return spriteY;<br />
}<br />
public byte getSpriteOrientation() {//设置精灵的方向<br />
  return 0;<br />
}<br />
public void updateSpritePosition(int arg0, int arg1) {<br />
  //更新精灵的位置，比如跑动是X及Y的坐标变化<br />
}<br />
public void paint(Graphics g) {<br />
  player.drawFrame(g);//绘制动作的帧<br />
}<br />
}</p>
<p>资源加载 ResourceLoader.java<br />
import java.io.IOException;<br />
import javax.microedition.lcdui.Image;<br />
import javax.microedition.lcdui.game.Sprite;<br />
import com.studio.motionwelder.MSprite;<br />
import com.studio.motionwelder.MSpriteImageLoader;<br />
public class ResourceLoader implements MSpriteImageLoader {<br />
private static ResourceLoader resLoader;// 单例<br />
private ResourceLoader() {<br />
}<br />
public static ResourceLoader getInstance() {// 获取ResourceLoader的实例<br />
  if (resLoader == null)<br />
   resLoader = new ResourceLoader();<br />
  return resLoader;<br />
}<br />
public Image[] loadImage(String spriteName, int imageId,<br />
   int orientationUsedInStudio) {// 整图形式加载图片<br />
  return null;<br />
}<br />
public Image[] loadImageClip(String spriteName, int imageId, int x, int y,<br />
   int w, int h, int orientationUsedInStudio) {// 切片形式加载图片<br />
  boolean doYouNeedHFlippedSpriteInYourgame = false;<br />
  boolean doYouNeedVFlippedSpriteInYourgame = false; // 是否有旋转操作<br />
  Image baseImage = null;<br />
  if (imageId == 0) {<br />
   baseImage = loadImage(&#8220;/hero.png&#8221;);<br />
   doYouNeedHFlippedSpriteInYourgame = false;<br />
   doYouNeedVFlippedSpriteInYourgame = false;<br />
  }<br />
  Image img[] = new Image[3];<br />
  img[0] = Image.createImage(baseImage, x, y, w, h, Sprite.TRANS_NONE); // 保存无旋转的切片<br />
  /** 如果使用了Nokia的图像操作就不要这样用，关于Nokia的操作作者在库代码里把它注释掉了 */<br />
  if (orientationUsedInStudio == MSprite.ORIENTATION_FLIP_H<br />
    || orientationUsedInStudio == MSprite.ORIENTATION_FLIP_BOTH_H_V<br />
    || doYouNeedHFlippedSpriteInYourgame)<br />
   img[1] = Image.createImage(baseImage, x, y, w, h,<br />
     Sprite.TRANS_MIRROR); // 保存水平旋转的切片<br />
  /** 如果使用了Nokia的图像操作就不要这样用，关于Nokia的操作作者在库代码里把它注释掉了 */<br />
  if (orientationUsedInStudio == MSprite.ORIENTATION_FLIP_V<br />
    || orientationUsedInStudio == MSprite.ORIENTATION_FLIP_BOTH_H_V<br />
    || doYouNeedVFlippedSpriteInYourgame)<br />
   img[2] = Image.createImage(baseImage, x, y, w, h,<br />
     Sprite.TRANS_MIRROR_ROT180); // 保存垂直旋转的切片<br />
  return img;<br />
}<br />
private Image loadImage(String imagePath) {<br />
  try {<br />
   Image img = Image.createImage(imagePath);<br />
   return img;<br />
  } catch (IOException e) {<br />
   e.printStackTrace();<br />
  }<br />
  return null;<br />
}<br />
}</p>
<p><a href="http://www.javagg.com/wp-content/uploads/2010/07/http_imgload.gif"><img class="alignnone size-full wp-image-801" title="http_imgload" src="http://www.javagg.com/wp-content/uploads/2010/07/http_imgload.gif" alt="" width="160" height="191" /></a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/800/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用动画编辑器编辑、绘制复杂的精灵动画</title>
		<link>http://www.javagg.com/archives/778</link>
		<comments>http://www.javagg.com/archives/778#comments</comments>
		<pubDate>Fri, 14 May 2010 14:08:23 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[spx]]></category>
		<category><![CDATA[动画编辑器]]></category>

		<guid isPermaLink="false">http://www.javagg.com/?p=778</guid>
		<description><![CDATA[我们平时所玩的很多游戏都有着非常绚丽的动画效果，尤其是像ACT、RPG等类型的游戏，必须拥有华丽的魔法和攻击效果才能吸引玩家的眼球。本文将主要介绍如何使用OPhone API以及动画编辑器类的工具来编辑、绘制和处理精灵的动画，整个程序的运行效果如下图所示：

图1 游戏最终效果
动画原理
我们都看过动画片，看过电影，玩过游戏，里面都有各种绚丽的动画，实际上动画的绘制机制概括说来就是以一定的速度连续播放静态的图片，这样人眼就能识别出动画。一般我们人眼能够分辨的动画速度为10——20帧/秒，我们称之为FPS（Frame Per Second），低于10帧就会变得很卡，高于20就会变成快动作，因此，控制好这个数值对游戏整体的流畅度至关重要。
那么总结起来，要想在游戏中绘制动画需要具备以下几个必要元素：
1. 动画的原始图片
2.动画序列数据
3.动画刷新机制（下一帧）
常规的动画播放方法
1.实现第一步（动画的原始图片）
常规的播放2D动画方法的方法实际就是对上述过程的一个分解：在游戏中，精灵的图片经常是被放置到一张图片上，下图就是一个典型的2D游戏精灵图片：

图2 角色原始图片
2.实现第二步（设定动画序列）
有了原始图片之后，我们就可以把这些图片按照一定的尺寸进行分割，切割成的每个块我们称之为“帧”，同时为每一帧进行编号，为每帧分配唯一的索引号，索引号可以从任意数字开始，可连续也可以随机，但要注意不能有重复的索引号，分配好的索引号可参照下图所示：
表1 游戏帧序列



0
1
2
3
4
5
6
7
8
9
10
11



 
有了这个索引，我们就可以为每个动画设定动画序列了，比如，我们可以分别定义精灵的上、下、左、右行走的动画序列，每个动画的序列如下面代码所示：
final static int ACTION_UP[]={0,1,2};
    final static int ACTION_DOWN[]={6,7,8};
    final static int ACTION_LEFT[]={9,10,11};
    final static int ACTION_RIGHT[]={3,4,5}; 
    final static int ACTION_STAND[]={7};  
数组中的每个元素值就是上面表格中的数值。
3.实现第三步（切换并播放动画）
　由于所有的图片块都被放置到了一个数组中保存起来，因此有个动画数据之后，我们就可以把数据所对应的图片绘制到屏幕上了，然后，通过线程来控制一帧一帧的切换，这就是游戏中动画处理的一般过程。
 
上面这种播放动画的方式的优点是开发简单，便于切换和控制，但是也有如下的一些缺点：
　　1.存在重复的图片资源
我们可以从原始图片上看到，如果要实现精灵向下走的动画，需要使用4帧图片，但是这4帧图片中只有精灵脚步的图片存在差异，剩下的都大致相同，这就是一种图片上的浪费。而我们的手机内存目前还比较小，因此这种浪费应该是要尽量避免的。
　　2.动画数据直接存在于代码中
上面的例子中，我们直接把动画的序列以数组的形式保存到了代码中，也就是说，把对动画数据的处理交给了程序员来完成，而程序员的主要工作应该是处理游戏中的算法逻辑，因此，比较好的解决方法是把动画的处理交给美工和策划来完成。因此，上面这种方法也存在缺点。
　　3.帧图片要求规整
如果采用上面的方法绘制动画，要求每一帧必须按照指定的长度和宽度进行分割，否则就是出现绘制错误，这在一定程度上也限制了程序的灵活性。
　　4. 难易实现复杂的动画效果
由于帧的尺寸人为的被限定，同时每一个动作就必须要一帧进行显示，如果要想实现复杂的动画序列就意味着要存在大量的帧序列，而原始图片势必要随之变得很大，进而增加了对内存的占用，而在这种情况下，帧数越多，重复的内容也会随之不断增多，显然这也不适合手机这种资源有限的设备的特点。
上面说了这些缺点，那么该如何解决呢？下面就为你介绍一下目前比较流行的一种动画处理方式，也是本文的重点——使用动画编辑工具。
作者介绍
李建，乐成数字通信学院 高级讲师。层就职于国内数家SP，CP公司，具有丰富的软件、游戏开发经验。并从事多年教学工作，具有丰富的教学经验。目前主要从事OPhone、J2ME开发和教学方面的工作。
动画编辑器的原理
动画编辑器就是一种软件工具，它的作用就是通过软件对原始图片进行切割，然后在软件中把切割好的图片块拼成一帧一帧的图片，再选择相应的图片来组成动画序列，最后将数据导出以文件。
动画编辑器的使用
目前，很多的手机游戏公司都在使用动画编辑器来制作动画，而不同的公司使用的工具也不尽相同，下图为一个功能比较强大且使用很广泛的动画编辑工具，界面如下图所示：

图3 动画编辑器界面
接下来我将一步一步的演示如何使用这个工具来制作动画：
1.         首先要建立一个工程，这个同时点击“”按钮引入一张图片，如下图：

图4 角色原始图片
从图中我们看到，原始图片不再是规则的帧序列，精灵图片被一块块的分解了。
2.         下面我们要对图片进行分割了，选中左边栏的“”，然后在图片上进行切割，把乌龟的各个零部件都用方块圈出来，最后的效果如下图：

图5 分割原始图片
3.         接下来就可以用这些“零件”拼图了。首先我们在右上方的窗口中点击“”按钮，接下来就可以看到右侧窗口变成如下图所示的界面：

图6 frame窗口
4.         接下来双击上图中的“1-Frame”，就会出现如下图所示界面：

图7 拼图界面
5.         接下来你就可以在左边的窗口中按住鼠标左键选择你要的乌龟的零部件图片并将其拖入右边窗口的坐标系中，一般将其放置到第一象限，一个拼好的帧图片如下图所示：

图8 帧的拼图
在拼图中，你可以使用左边的一些按钮来实现各个图块的位置和对齐，如图：

图9 布局排列按钮
可以点击“”来回到帧列表界面，同时可以使用“”按键增加新的帧。按照上述方法可以拼出乌龟的上、下、左、右行走等各个帧序列，拼好的效果如下图：

图10 拼好的各个帧
6.         有了帧图片就可以利用它们来组成动画了，方法如下：
菜单中选择“Action——Edit”，效果如下图：

图11 增加动画

图12 动画编辑界面
7.         接下来在“Action Edit”窗口中通过“”按钮增加一个动画，然后就可以从Frame列表中选择相应的帧来组成相应动画了，如下图所示：

图13 设置动画
这样我们就制作好了一个乌龟向下行走的动画，同时你可以点击“”按钮来观察这个动画，并根据效果对动画进行调整，非常方便。
现在我们已经完成了整个动画的制作过程，下面就要将数据进行导出，过程如下图所示：

图14 导出数据
上面介绍了如何使用动画编辑器来设定动画，相信你已经掌握了这个工具的使用了。但是，用这个工具制作的动画并不能直接显示到手机屏幕上，还需要我们通过代码的方式来对其进行处理。下面来介绍一下如何通过代码来绘制响应的动画。
动画播放类——Animation的实现：
要想实现对动画的播放必须要有一个动画的解析类，也就是需要对“.sprite”数据文件进行解析，这里我们将这个类命名为SpriteX，这个类的作用是解析数据文件并提供动画的绘制方法，因该类内容较多，此处没有贴出源代码，请参考附件。
精灵类——Role的实现
每个精灵类都需要有个SpriteX类的对象用来处理该精灵的动画，因此需要在这个类中定义如下属性：
SpriteX spx;     
精灵类的构造方法如下：

public Role(GameView view)  
 
    {  
 
       spx=new SpriteX("s.sprite",R.drawable.a2,view);  
 
    } 

这里面的“view”为视图类的对象，稍后会有介绍。
注意：精灵图片需要放置到“res/drawable”文件夹，动画数据要放到“assets”文件夹下面。
精灵类的绘制方法如下：

public void paint(Canvas g)  
 
    {  
 
        spx.paint(g,100,100);  
 
        spx.nextFrame(); [...]]]></description>
			<content:encoded><![CDATA[<p>我们平时所玩的很多游戏都有着非常绚丽的动画效果，尤其是像ACT、RPG等类型的游戏，必须拥有华丽的魔法和攻击效果才能吸引玩家的眼球。本文将主要介绍如何使用OPhone API以及动画编辑器类的工具来编辑、绘制和处理精灵的动画，整个程序的运行效果如下图所示：<span id="more-778"></span></p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1USKS8-0.png" type="text" /><br />
图1 游戏最终效果</p>
<h1>动画原理</h1>
<p>我们都看过动画片，看过电影，玩过游戏，里面都有各种绚丽的动画，实际上动画的绘制机制概括说来就是以一定的速度连续播放静态的图片，这样人眼就能识别出动画。一般我们人眼能够分辨的动画速度为10——20帧/秒，我们称之为FPS（Frame Per Second），低于10帧就会变得很卡，高于20就会变成快动作，因此，控制好这个数值对游戏整体的流畅度至关重要。</p>
<p>那么总结起来，要想在游戏中绘制动画需要具备以下几个必要元素：</p>
<p>1. 动画的原始图片</p>
<p>2.动画序列数据</p>
<p>3.动画刷新机制（下一帧）</p>
<h1>常规的动画播放方法</h1>
<p><strong>1.</strong><strong>实现第一步（动画的原始图片）</strong></p>
<p>常规的播放2D动画方法的方法实际就是对上述过程的一个分解：在游戏中，精灵的图片经常是被放置到一张图片上，下图就是一个典型的2D游戏精灵图片：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1USLN2-1.png" alt="" /><br />
图2 角色原始图片</p>
<p><strong>2.</strong><strong>实现第二步（设定动画序列）</strong></p>
<p>有了原始图片之后，我们就可以把这些图片按照一定的尺寸进行分割，切割成的每个块我们称之为“帧”，同时为每一帧进行编号，为每帧分配唯一的索引号，索引号可以从任意数字开始，可连续也可以随机，但要注意不能有重复的索引号，分配好的索引号可参照下图所示：</p>
<p>表1 游戏帧序列</p>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td width="47" valign="top">0</td>
<td width="47" valign="top">1</td>
<td width="47" valign="top">2</td>
<td width="47" valign="top">3</td>
<td width="47" valign="top">4</td>
<td width="47" valign="top">5</td>
<td width="47" valign="top">6</td>
<td width="47" valign="top">7</td>
<td width="47" valign="top">8</td>
<td width="47" valign="top">9</td>
<td width="47" valign="top">10</td>
<td width="47" valign="top">11</td>
</tr>
</tbody>
</table>
<p> </p>
<p>有了这个索引，我们就可以为每个动画设定动画序列了，比如，我们可以分别定义精灵的上、下、左、右行走的动画序列，每个动画的序列如下面代码所示：</p>
<p><strong>final</strong> <strong>static</strong> <strong>int</strong> <em>ACTION_UP</em>[]={0,1,2};</p>
<p>    <strong>final</strong> <strong>static</strong> <strong>int</strong> <em>ACTION_DOWN</em>[]={6,7,8};</p>
<p>    <strong>final</strong> <strong>static</strong> <strong>int</strong> <em>ACTION_LEFT</em>[]={9,10,11};</p>
<p>    <strong>final</strong> <strong>static</strong> <strong>int</strong> <em>ACTION_RIGHT</em>[]={3,4,5}; </p>
<p>    <strong>final</strong> <strong>static</strong> <strong>int</strong> <em>ACTION_STAND</em>[]={7};  </p>
<p>数组中的每个元素值就是上面表格中的数值。</p>
<p><strong>3.</strong><strong>实现第三步（切换并播放动画）</strong><br />
　由于所有的图片块都被放置到了一个数组中保存起来，因此有个动画数据之后，我们就可以把数据所对应的图片绘制到屏幕上了，然后，通过线程来控制一帧一帧的切换，这就是游戏中动画处理的一般过程。</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1USL004-2.png" type="text" /> </p>
<p>上面这种播放动画的方式的优点是开发简单，便于切换和控制，但是也有如下的一些缺点：</p>
<p>　　1.存在重复的图片资源</p>
<p>我们可以从原始图片上看到，如果要实现精灵向下走的动画，需要使用4帧图片，但是这4帧图片中只有精灵脚步的图片存在差异，剩下的都大致相同，这就是一种图片上的浪费。而我们的手机内存目前还比较小，因此这种浪费应该是要尽量避免的。</p>
<p>　　2.动画数据直接存在于代码中</p>
<p>上面的例子中，我们直接把动画的序列以数组的形式保存到了代码中，也就是说，把对动画数据的处理交给了程序员来完成，而程序员的主要工作应该是处理游戏中的算法逻辑，因此，比较好的解决方法是把动画的处理交给美工和策划来完成。因此，上面这种方法也存在缺点。</p>
<p>　　3.帧图片要求规整</p>
<p>如果采用上面的方法绘制动画，要求每一帧必须按照指定的长度和宽度进行分割，否则就是出现绘制错误，这在一定程度上也限制了程序的灵活性。</p>
<p>　　4. 难易实现复杂的动画效果</p>
<p>由于帧的尺寸人为的被限定，同时每一个动作就必须要一帧进行显示，如果要想实现复杂的动画序列就意味着要存在大量的帧序列，而原始图片势必要随之变得很大，进而增加了对内存的占用，而在这种情况下，帧数越多，重复的内容也会随之不断增多，显然这也不适合手机这种资源有限的设备的特点。</p>
<p>上面说了这些缺点，那么该如何解决呢？下面就为你介绍一下目前比较流行的一种动画处理方式，也是本文的重点——使用动画编辑工具。</p>
<h1>作者介绍</h1>
<p>李建，乐成数字通信学院 高级讲师。层就职于国内数家SP，CP公司，具有丰富的软件、游戏开发经验。并从事多年教学工作，具有丰富的教学经验。目前主要从事OPhone、J2ME开发和教学方面的工作。</p>
<h1>动画编辑器的原理</h1>
<p>动画编辑器就是一种软件工具，它的作用就是通过软件对原始图片进行切割，然后在软件中把切割好的图片块拼成一帧一帧的图片，再选择相应的图片来组成动画序列，最后将数据导出以文件。</p>
<h1>动画编辑器的使用</h1>
<p>目前，很多的手机游戏公司都在使用动画编辑器来制作动画，而不同的公司使用的工具也不尽相同，下图为一个功能比较强大且使用很广泛的动画编辑工具，界面如下图所示：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35I151-0.png" type="text" /></p>
<p>图3 动画编辑器界面</p>
<p>接下来我将一步一步的演示如何使用这个工具来制作动画：</p>
<p>1.         首先要建立一个工程，这个同时点击“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35MS8-1.png" type="text" />”按钮引入一张图片，如下图：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35M008-2.png" type="text" /></p>
<p>图4 角色原始图片</p>
<p>从图中我们看到，原始图片不再是规则的帧序列，精灵图片被一块块的分解了。</p>
<p>2.         下面我们要对图片进行分割了，选中左边栏的“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35IG8-3.png" type="text" />”，然后在图片上进行切割，把乌龟的各个零部件都用方块圈出来，最后的效果如下图：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35LF4-4.png" type="text" /></p>
<p>图5 分割原始图片</p>
<p>3.         接下来就可以用这些“零件”拼图了。首先我们在右上方的窗口中点击“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35L2L-5.png" type="text" />”按钮，接下来就可以看到右侧窗口变成如下图所示的界面：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35M430-6.png" type="text" /></p>
<p>图6 frame窗口</p>
<p>4.         接下来双击上图中的“1-Frame”，就会出现如下图所示界面：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35H315-7.png" type="text" /></p>
<p>图7 拼图界面</p>
<p>5.         接下来你就可以在左边的窗口中按住鼠标左键选择你要的乌龟的零部件图片并将其拖入右边窗口的坐标系中，一般将其放置到第一象限，一个拼好的帧图片如下图所示：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35L258-8.png" type="text" /></p>
<p>图8 帧的拼图</p>
<p>在拼图中，你可以使用左边的一些按钮来实现各个图块的位置和对齐，如图：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35M635-9.png" type="text" /></p>
<p>图9 布局排列按钮</p>
<p>可以点击“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35KP9-10.png" type="text" />”来回到帧列表界面，同时可以使用“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35G496-11.png" type="text" />”按键增加新的帧。按照上述方法可以拼出乌龟的上、下、左、右行走等各个帧序列，拼好的效果如下图：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35M0H-12.png" type="text" /></p>
<p>图10 拼好的各个帧</p>
<p>6.         有了帧图片就可以利用它们来组成动画了，方法如下：</p>
<p>菜单中选择“Action——Edit”，效果如下图：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35M5a-13.png" type="text" /></p>
<p>图11 增加动画</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35K624-14.png" type="text" /></p>
<p>图12 动画编辑界面</p>
<p>7.         接下来在“Action Edit”窗口中通过“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35M555-15.png" type="text" />”按钮增加一个动画，然后就可以从Frame列表中选择相应的帧来组成相应动画了，如下图所示：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35K212-16.png" type="text" /></p>
<p>图13 设置动画</p>
<p>这样我们就制作好了一个乌龟向下行走的动画，同时你可以点击“<img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35J227-17.png" type="text" />”按钮来观察这个动画，并根据效果对动画进行调整，非常方便。</p>
<p>现在我们已经完成了整个动画的制作过程，下面就要将数据进行导出，过程如下图所示：</p>
<p><img src="http://www.ldci.com.cn/uploads/allimg/100123/1Z35KY8-18.png" type="text" /></p>
<p>图14 导出数据</p>
<p>上面介绍了如何使用动画编辑器来设定动画，相信你已经掌握了这个工具的使用了。但是，用这个工具制作的动画并不能直接显示到手机屏幕上，还需要我们通过代码的方式来对其进行处理。下面来介绍一下如何通过代码来绘制响应的动画。</p>
<h1>动画播放类——Animation的实现：</h1>
<p>要想实现对动画的播放必须要有一个动画的解析类，也就是需要对“.sprite”数据文件进行解析，这里我们将这个类命名为SpriteX，这个类的作用是解析数据文件并提供动画的绘制方法，因该类内容较多，此处没有贴出源代码，请参考附件。</p>
<h1>精灵类——Role的实现</h1>
<p>每个精灵类都需要有个SpriteX类的对象用来处理该精灵的动画，因此需要在这个类中定义如下属性：</p>
<p>SpriteX spx;     </p>
<p>精灵类的构造方法如下：</p>
<pre>
<li>public Role(GameView view)  </li>
<li> </li>
<li>    {  </li>
<li> </li>
<li>       spx=new SpriteX("s.sprite",R.drawable.a2,view);  </li>
<li> </li>
<li>    } </li>
</pre>
<p>这里面的“view”为视图类的对象，稍后会有介绍。</p>
<p><strong>注意：精灵图片需要放置到“res/drawable”文件夹，动画数据要放到“assets”文件夹下面。</strong></p>
<p>精灵类的绘制方法如下：</p>
<pre>
<li>public void paint(Canvas g)  </li>
<li> </li>
<li>    {  </li>
<li> </li>
<li>        spx.paint(g,100,100);  </li>
<li> </li>
<li>        spx.nextFrame();  </li>
<li> </li>
<li>    } </li>
</pre>
<p>设计屏幕类</p>
<p>定义好精灵类只是实现了这个项目的第一步，我们还不能在屏幕上看到精灵的动画，我们需要一个视图来把精灵显示出来，接下来我们定义视图类，在这里我们自定义一个类GameView来实现这个功能。作为一个自定义的视图类，这个类需要继承View，关于这个类请参考api文档。这个类用来处理精灵的绘制，按键处理等功能。其构造方法如下：</p>
<pre>
<li>public GameView(Context view)  </li>
<li> </li>
<li>    {  </li>
<li> </li>
<li>       super(view);  </li>
<li> </li>
<li>        </li>
<li> </li>
<li>       gamePaint = new Paint();  </li>
<li> </li>
<li>       player=new Role(this);  </li>
<li> </li>
<li>   </li>
<li> </li>
<li>       // 建立线程  </li>
<li> </li>
<li>       Thread t = new Thread(this);  </li>
<li> </li>
<li>       t.start();  </li>
<li> </li>
<li>} </li>
</pre>
<p>精灵对象创建完毕后，我们就可以将其绘制到屏幕上了，这里需要重写View类中的onDraw()方法，此方法会在该类对象被Activity调用时自动调用，其方法如下：</p>
<pre>
<li>@Override  </li>
<li> </li>
<li>  protected void onDraw(Canvas g)  </li>
<li> </li>
<li>  {  </li>
<li> </li>
<li>     role.draw(gamePaint);  </li>
<li> </li>
<li>  } </li>
</pre>
<p> </p>
<h1>动画的刷新</h1>
<p>在GameView类中需要处理动画的刷新，也就是每隔一段时间来播放动画的下一帧，因此我们用线程来实现这个功能，线程的run方法如下所示：</p>
<pre>
<li>public void run()  </li>
<li> </li>
<li>    {  </li>
<li> </li>
<li>       while (true)  </li>
<li> </li>
<li>       {  </li>
<li> </li>
<li>           // 放慢速度  </li>
<li> </li>
<li>           long bm = System.currentTimeMillis();  </li>
<li> </li>
<li>           // 更新屏幕  </li>
<li> </li>
<li>           postInvalidate();  </li>
<li> </li>
<li>           long cm = System.currentTimeMillis();  </li>
<li> </li>
<li>           if (cm - bm &lt; SPLASH_RATE)  </li>
<li> </li>
<li>              try  </li>
<li> </li>
<li>              {  </li>
<li> </li>
<li>                  Thread.sleep(SPLASH_RATE - (cm - bm));  </li>
<li> </li>
<li>              } catch (InterruptedException e)  </li>
<li> </li>
<li>              {  </li>
<li> </li>
<li>                  e.printStackTrace();  </li>
<li> </li>
<li>              }  </li>
<li> </li>
<li>       }  </li>
<li> </li>
<li>    } </li>
</pre>
<p>在这里要注意给线程适当的休眠时间，用来控制FPS，这样有利于得到更好的游戏体验。</p>
<p><strong>注意：</strong><strong>SPLASH_RATE</strong><strong>就是每个线程的间隔时间</strong></p>
<h1>定义Activity</h1>
<p>最后我们定义一个Activity的子类用来运行该游戏，在Activitiy中我们需要创一个GameView对象，然后通过setContentView()方法进行设定，代码如下：</p>
<pre>
<li>@Override  </li>
<li> </li>
<li>    public void onCreate(Bundle savedInstanceState)  </li>
<li> </li>
<li>    {  </li>
<li> </li>
<li>        super.onCreate(savedInstanceState);  </li>
<li> </li>
<li>        instance=this;  </li>
<li> </li>
<li>         </li>
<li> </li>
<li>        view=new GameView(this);  </li>
<li> </li>
<li>        setContentView(view);  </li>
<li> </li>
<li>} </li>
</pre>
<p>到此，我们已经完成了所有的功能，你可以运行模拟器并观察其效果了。</p>
<h1>总结</h1>
<p>使用动画编辑工具的方法可以非常方便的开发复杂的动画效果，尽可能的节约有限的内存资源并且使程序员和策划、美工的工作相分离，是现在手机端2D游戏开发普遍采用的一种高效、方便的方法。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/778/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>J2ME平台PNG图片的压缩与解压缩</title>
		<link>http://www.javagg.com/archives/718</link>
		<comments>http://www.javagg.com/archives/718#comments</comments>
		<pubDate>Fri, 02 Apr 2010 08:20:53 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[png]]></category>
		<category><![CDATA[压缩]]></category>

		<guid isPermaLink="false">http://www.javagg.com/archives/718</guid>
		<description><![CDATA[在J2ME平台上PNG图片格式几乎成为了标准，无数台手持设备上运行的J2ME程序几乎都选用PNG来显示图像，包括大量的手机游戏以及手机应用，所以对PNG文件格式的了解，可以更有效的减少Jar Size，保护自有知识产权。
PNG文件格式：
PNG文件格式分为PNG-24和PNG-8，其最大的区别是PNG-24是用24位来保存一个像素值，是真彩色，而PNG-8是用8位索引值来在 调色盘中索引一个颜色，因为一个索引值的最大上限为2的8次方既128，故调色盘中颜色数最多为128种，所以该文件格式又被叫做PNG-8 128仿色。
PNG-24因为其图片容量过大，而且在Nokia和Moto等某些机型上创建图片失败和显示不正确等异常时有发生，有时还会严重拖慢显示速度，故并不常 用，CoCoMo认为这些异常和平台底层的图像解压不无关系。不过该格式最大的优点是可以保存Alpha通道，同事也曾有过利用该图片格式实现Alpha 混合的先例，想来随着技术的发展，手机硬件平台的提升，Alpha混合一定会被广泛的应用，到那时该格式的最大优势才会真正发挥。
PNG-8文件是目前广泛应用的PNG图像格式，其主要有六大块组成：
1.文件头
2.IHDR块
3.PLTE块
4.tRNS块
5.IDAT块
6.文件尾
这六大块按顺序排列，也就是说IDAT块永远是在PLTE块之后，期间也会有许多其他的区块用来描述信息，例如图像的最后修改时间是多少，图像的创建者是谁等，不过这些区块的信息对我们来说都是可有可无的描述信息，故压缩时一般先向这些区块开刀。
数据块：
除了文件头，其中四大数据块和文件尾都是由统一的数据块文件结构描述的：
Chunk Length: 4byte
Chunk Type:   4byte
Chunk Data:   Chunk Length的长度
Chunk CRC:    4byte
例如IHDR块的数据长度为13，既
Chunk Length = 13
Chunk Type = &#8220;IHDR&#8221;
文件头：
用来标示PNG文件，为固定的64个字节：0&#215;89504e47 0&#215;0d0a1a0a
IHDR块：
用来描述图像的基本信息，其格式为：
图像宽：    4byte
图像高：    4byte
图像色深： 4byte
颜色类型： 1byte
压缩方法： 1byte
滤波方法： 1byte
扫描方法： 1byte
曾经有人问过我，撒叫滤波方法和扫描方法，汗，说实话我也不知道，不过我们是在做手机游戏，不是在搞图形学不是嘛。
PLTE块：
这个就是传说中放置调色盘数据的地方啦，其格式为：
循环
RED：    1byte
GREEN：1byte
BLUE：  1byte
END
循环长度嘛，不就是Chunk Length / 3的长度嘛，而且Chunk Length一定为3的倍数。
tRNS块：
这个块时有时无，主要是看你是否使用了透明色。该区块的格式为：
循环
if(对应调色盘颜色非透明)
0xFF：  1byte
else
0&#215;00：  1byte
END
循环长度为调色盘的颜色数，相当于调色盘颜色表的一个对应表，标识该颜色是否透明，0xFF不透明，0&#215;00透明。故如果用UltraEdit查看PNG文件的二进制编码，如果看到一大片FF，一般就是tRNS区块啦，因为一个PNG文件一般只有一个透明色。
IDAT块：
这个就是存放图像数据的地方啦，这里要注意的是一个PNG文件可能有多个IDAT区块，而其他三大区块只可能有一个。
IDAT区块是经过压缩的，所以数据不可读，压缩算法一般为LZ77滑动窗口算法，如果硬要看里面的数据的话，用zlib库也是可以的，CoCoMo当年 就见过Windows Mobile上的帝国时代巨变态的用zlib库压缩和解压该区块来进一步减少PNG文件大小，真是寸K寸金啊。
IEND块：
该区块虽然也按照数据块的结构，但Chunk Data是没有的，所以是固定的96个字节：0&#215;00000000 0&#215;49454e44 0xae426082
PNG图像压缩：
了解了PNG的文件结构，压缩就有的放矢了。压缩有6个级别，可以根据需要选择。
Level1：读取PNG文件，将除六大块之外的所有区块都过滤掉
Level2：文件头是固定的0&#215;89504e47 0&#215;0d0a1a0a，文件尾是固定的0&#215;00000000 0&#215;49454e44 0xae426082，去掉！
Level3：每个区块的Chunk Type我们是否需要呢？很明显，我们自己写的压缩格式自己应该清楚是按照什么样的顺序，去掉！
Level4：每个区块的Chunk Length我们是否需要呢？
IHDR块：定长13个字节，明显不需要，去掉。
PLTE块：最多128个颜色，为撒要用4byte来记录区块长度而不是用1byte来记录颜色数呢？
tRNS块：既然有颜色数，tRNS又是调色盘颜色表的对应表，既数量与颜色数相同，为撒还需要呢？
IDAT块：我想这个是唯一需要4byte来记录长度的区块。
Level5：每个区块的Chunk CRC是否需要呢？
因为计算CRC需要一些时间，但对于字节较少的区块一般可以忽略不计，所以对于这个问题还是由程序员自己决定吧。对于CRC的计算可以参看CoCoMo的另一篇Blog“PNG文件的CRC码计算”
Level6：每个区块我们是否要原封不动的保存期数据呢？
IHDR块：除了宽、高、色深是需要的，后面那4byte的信息是固定的0&#215;03000000
PLTE块：为撒要用3byte来表示RGB而不是2byte的565格式？压缩方法可以参看CoCoMo的另一篇Blog“关于PNG图像压缩的一点感悟”
tRNS块：我想tRNS块是冗余最多的区块了吧，大段大段的0xFF明显没有必要，一般的PNG文件只有一个透明色，为撒要用对应表的方法而不是一个索 引来记录到底哪个是透明色呢？由于颜色数最多128，所以只需1byte就可以代替tRNS那么多0xFF啦。
IDAT块：么想法，如果你够变态，把zlib加进来吧！
PNG图像解压：
创建了自定义的文件，J2ME端读取后，就面临解压的问题了。我们可以利用此函数来创建Image：
static Image
createImage(byte[] imageData, int imageOffset, int [...]]]></description>
			<content:encoded><![CDATA[<div id="blog_text">在J2ME平台上PNG图片格式几乎成为了标准，无数台手持设备上运行的J2ME程序几乎都选用PNG来显示图像，包括大量的手机游戏以及手机应用，所以对PNG文件格式的了解，可以更有效的减少Jar Size，保护自有知识产权。</p>
<p>PNG文件格式：<br />
PNG文件格式分为PNG-24和PNG-8，其最大的区别是PNG-24是用24位来保存一个像素值，是真彩色，而PNG-8是用8位索引值来在 调色盘中索引一个颜色，因为一个索引值的最大上限为2的8次方既128，故调色盘中颜色数最多为128种，所以该文件格式又被叫做PNG-8 128仿色。<br />
PNG-24因为其图片容量过大，而且在Nokia和Moto等某些机型上创建图片失败和显示不正确等异常时有发生，有时还会严重拖慢显示速度，故并不常 用，CoCoMo认为这些异常和平台底层的图像解压不无关系。不过该格式最大的优点是可以保存Alpha通道，同事也曾有过利用该图片格式实现Alpha 混合的先例，想来随着技术的发展，手机硬件平台的提升，Alpha混合一定会被广泛的应用，到那时该格式的最大优势才会真正发挥。<br />
PNG-8文件是目前广泛应用的PNG图像格式，其主要有六大块组成：<br />
1.文件头<br />
2.IHDR块<br />
3.PLTE块<br />
4.tRNS块<br />
5.IDAT块<br />
6.文件尾<br />
这六大块按顺序排列，也就是说IDAT块永远是在PLTE块之后，期间也会有许多其他的区块用来描述信息，例如图像的最后修改时间是多少，图像的创建者是谁等，不过这些区块的信息对我们来说都是可有可无的描述信息，故压缩时一般先向这些区块开刀。<span id="more-718"></span></p>
<p>数据块：<br />
除了文件头，其中四大数据块和文件尾都是由统一的数据块文件结构描述的：<br />
Chunk Length: 4byte<br />
Chunk Type:   4byte<br />
Chunk Data:   Chunk Length的长度<br />
Chunk CRC:    4byte<br />
例如IHDR块的数据长度为13，既<br />
Chunk Length = 13<br />
Chunk Type = &#8220;IHDR&#8221;</p>
<p>文件头：<br />
用来标示PNG文件，为固定的64个字节：0&#215;89504e47 0&#215;0d0a1a0a</p>
<p>IHDR块：<br />
用来描述图像的基本信息，其格式为：<br />
图像宽：    4byte<br />
图像高：    4byte<br />
图像色深： 4byte<br />
颜色类型： 1byte<br />
压缩方法： 1byte<br />
滤波方法： 1byte<br />
扫描方法： 1byte<br />
曾经有人问过我，撒叫滤波方法和扫描方法，汗，说实话我也不知道，不过我们是在做手机游戏，不是在搞图形学不是嘛。</p>
<p>PLTE块：<br />
这个就是传说中放置调色盘数据的地方啦，其格式为：<br />
循环<br />
RED：    1byte<br />
GREEN：1byte<br />
BLUE：  1byte<br />
END<br />
循环长度嘛，不就是Chunk Length / 3的长度嘛，而且Chunk Length一定为3的倍数。</p>
<p>tRNS块：<br />
这个块时有时无，主要是看你是否使用了透明色。该区块的格式为：<br />
循环<br />
if(对应调色盘颜色非透明)<br />
0xFF：  1byte<br />
else<br />
0&#215;00：  1byte<br />
END<br />
循环长度为调色盘的颜色数，相当于调色盘颜色表的一个对应表，标识该颜色是否透明，0xFF不透明，0&#215;00透明。故如果用UltraEdit查看PNG文件的二进制编码，如果看到一大片FF，一般就是tRNS区块啦，因为一个PNG文件一般只有一个透明色。</p>
<p>IDAT块：<br />
这个就是存放图像数据的地方啦，这里要注意的是一个PNG文件可能有多个IDAT区块，而其他三大区块只可能有一个。<br />
IDAT区块是经过压缩的，所以数据不可读，压缩算法一般为LZ77滑动窗口算法，如果硬要看里面的数据的话，用zlib库也是可以的，CoCoMo当年 就见过Windows Mobile上的帝国时代巨变态的用zlib库压缩和解压该区块来进一步减少PNG文件大小，真是寸K寸金啊。</p>
<p>IEND块：<br />
该区块虽然也按照数据块的结构，但Chunk Data是没有的，所以是固定的96个字节：0&#215;00000000 0&#215;49454e44 0xae426082</p>
<p>PNG图像压缩：<br />
了解了PNG的文件结构，压缩就有的放矢了。压缩有6个级别，可以根据需要选择。<br />
Level1：读取PNG文件，将除六大块之外的所有区块都过滤掉<br />
Level2：文件头是固定的0&#215;89504e47 0&#215;0d0a1a0a，文件尾是固定的0&#215;00000000 0&#215;49454e44 0xae426082，去掉！<br />
Level3：每个区块的Chunk Type我们是否需要呢？很明显，我们自己写的压缩格式自己应该清楚是按照什么样的顺序，去掉！<br />
Level4：每个区块的Chunk Length我们是否需要呢？<br />
IHDR块：定长13个字节，明显不需要，去掉。<br />
PLTE块：最多128个颜色，为撒要用4byte来记录区块长度而不是用1byte来记录颜色数呢？<br />
tRNS块：既然有颜色数，tRNS又是调色盘颜色表的对应表，既数量与颜色数相同，为撒还需要呢？<br />
IDAT块：我想这个是唯一需要4byte来记录长度的区块。<br />
Level5：每个区块的Chunk CRC是否需要呢？<br />
因为计算CRC需要一些时间，但对于字节较少的区块一般可以忽略不计，所以对于这个问题还是由程序员自己决定吧。对于CRC的计算可以参看CoCoMo的另一篇Blog“PNG文件的CRC码计算”<br />
Level6：每个区块我们是否要原封不动的保存期数据呢？<br />
IHDR块：除了宽、高、色深是需要的，后面那4byte的信息是固定的0&#215;03000000<br />
PLTE块：为撒要用3byte来表示RGB而不是2byte的565格式？压缩方法可以参看CoCoMo的另一篇Blog“关于PNG图像压缩的一点感悟”<br />
tRNS块：我想tRNS块是冗余最多的区块了吧，大段大段的0xFF明显没有必要，一般的PNG文件只有一个透明色，为撒要用对应表的方法而不是一个索 引来记录到底哪个是透明色呢？由于颜色数最多128，所以只需1byte就可以代替tRNS那么多0xFF啦。<br />
IDAT块：么想法，如果你够变态，把zlib加进来吧！</p>
<p>PNG图像解压：<br />
创建了自定义的文件，J2ME端读取后，就面临解压的问题了。我们可以利用此函数来创建Image：<br />
static Image<br />
createImage(byte[] imageData, int imageOffset, int imageLength)<br />
前提是传入的imageData与PNG未被压缩前的一致。因为PNG文件格式是固定的，所以读取自定义的压缩文件后，开始将那些默认的数据再添加进去，实现解压的目的。下面就开始解压之旅吧!<br />
首先要创建一个ByteArrayOutputStream out，<br />
1.写入文件头：<br />
out.writeInt(0&#215;89504e47);<br />
out.writeInt(0&#215;0d0a1a0a);<br />
2.写入IHDR块<br />
out.writeInt(13);<br />
out.writeInt(0&#215;49484452);  //0&#215;49484452为Chunk Type &#8220;IHDR&#8221;<br />
out.writeInt(width);<br />
out.writeInt(height);<br />
out.writeByte(depth);<br />
out.writeInt(0&#215;03000000);  //压缩时舍掉的4byte，默认0&#215;03000000<br />
out.writeInt(crc);<br />
其他区块方法一致，故略过。。。<br />
3.写入文件尾<br />
out.writeInt(0&#215;00000000);<br />
out.writeInt(0&#215;49454e44);<br />
out.writeInt(0xae426082);<br />
4.转换成数组，创建Image<br />
byte[] pngBuffer = out.toByteArray();<br />
Image image = Image.createImage(pngBuffer, 0, pngBuffer.length);<br />
哈哈，大功告成。这里注意如果中途数据写入有错误，经常会出现创建Image失败的异常，而且非常不好调试，不过只要自定的压缩格式定下来后，对应的创建Image的函数只要写一次，以后基本不会出问题哈。</p>
<p>PNG图像加解密：<br />
很多人都担心自己辛苦创作的漂亮的美术图片很easy就被别人拿到了，究其原因是由于PNG文件格式是固定的，稍微了解的人用UltraEdit很 容易就能找到IHDR，PLTE等标识了。CoCoMo就经常看GameLoft的图像文件，哈哈。一般是2byte的Length，然后紧接着图片数 据，都放在一个文件里，直接拷贝2进制然后粘贴到一个新文件里就是一幅图。后来的加密技术会把PNG分块，例如前100个字节一块，紧接着1K一块，最后 剩余字节一块，然后把块顺序打乱，用2byte来记录总长度，1byte记录顺序，但是这并没有从根本上消除IHDR，IEND这些显眼的定位标识，好像 在对破解者说：嘿，看，我就在这里！<br />
现在了解了之前的压缩和解压技术，这个问题也就迎刃而解了，因为Chunk Length，Chunk Type和Chunk CRC这些东西都消失了，甚至连数据块本身的数据都修改了，我可以按照ImageWidth、ImageHeight、ImageDepth的顺序写数 据，也可以倒过来写。我想再牛的PNG分析器也是无能为力的吧，唯一可以定位的就只有IDAT区块了，不过就算得到该区块的数据，也应该是一张黑白图。</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/718/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>应用双缓冲技术解决画面闪烁的问题</title>
		<link>http://www.javagg.com/archives/566</link>
		<comments>http://www.javagg.com/archives/566#comments</comments>
		<pubDate>Fri, 05 Mar 2010 15:36:01 +0000</pubDate>
		<dc:creator>纯净水</dc:creator>
				<category><![CDATA[j2me]]></category>
		<category><![CDATA[java]]></category>
		<category><![CDATA[游戏]]></category>

		<guid isPermaLink="false">eric_DIARY_105790599</guid>
		<description><![CDATA[有些时候我们可能在J2ME中遇到画面闪烁的问题，这时候我们可以应用双缓冲的技术来解决，不过由于现在越来越多的手机自身就支持双缓冲了。所以这里只做个简单的介绍。
我写了程序本来想在NOkia 6108上比较用和不用的区别，结果这个手机自己就支持双缓冲，所以根本没有比较出来。不过了解这个技术还是有必要的，所以我决定还是写出来。双缓冲本来是在开发PC应用程序的时候遇到的。在MIDP开发中同样存在，当你在屏幕上进行原始写画的时候，如果很复杂的话，用户会发现界面在闪烁。因此你可以这样做，首先在另一个图片上进行paint()得操作，当完成了以后就把它copy到屏幕上，由于通常copy得时候速度很快就不会出现闪烁了。这个技术就是双缓冲。
Canvas类提供了isDoubleBuffered()方法来判断设备是不是支持这个功能，如果返回true的话，那么我们就没有必要使用双缓冲了，如果false的话，我们可以这么做：
public DoubleCanvas(UIController uicontroller)
{
super();
this.uicontroller = uicontroller;
width = this.getWidth();
height = this.getHeight();
this.setCommandListener(this);
if(!isDoubleBuffered())
{
offImage = Image.createImage(width,height);
}
}
protected void paint(Graphics arg0)
{
arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER&#124;Graphics.TOP);
 Graphics saved = arg0;
if(offImage != null)
{
arg0 = offImage.getGraphics();
}
arg0.setColor(255,128,128);
for(int i = 2,j=2;i&#60;width/2-6&#38;&#38;j&#60;height/2-6;i=i+2,j=j+2)
{
arg0.drawRect(i,j,width-2*i,height-2*j);
}
if(arg0 != saved)
{
saved.drawImage(offImage,0,0,Graphics.LEFT&#124;Graphics.TOP);
}
 }
得到offImage得Graphics实例后，进行paint()得操作。这个部分通常比较复杂，我这里的不够复杂：）
然后把offImage直接copy到屏幕上也就是执行saved.drawImage(offImage,0,0,Graphics.LEFT&#124;Graphics.TOP);

 我写了一个应用程序来比较使用和不使用双缓冲的效果，但是由于我的手机支持双缓冲所以看不出效果，如果你有兴趣，那么可以把paint()部分的代码修改的复杂一些然后再移植到不支持的手机上也许可以看出效果，下面是我程序的代码：
import javax.microedition.midlet.MIDlet;
import javax.microedition.midlet.MIDletStateChangeException;


public class DoubleBufferMIDlet extends MIDlet
{
private UIController uicontroller;
protected void startApp() throws MIDletStateChangeException
{
uicontroller = new UIController(this);
uicontroller.init();
 }
 protected void pauseApp()
{

 }

protected void destroyApp(boolean arg0) throws MIDletStateChangeException
{
 [...]]]></description>
			<content:encoded><![CDATA[<p>有些时候我们可能在J2ME中遇到画面闪烁的问题，这时候我们可以应用双缓冲的技术来解决，不过由于现在越来越多的手机自身就支持双缓冲了。所以这里只做个简单的介绍。</p>
<p>我写了程序本来想在NOkia 6108上比较用和不用的区别，结果这个手机自己就支持双缓冲，所以根本没有比较出来。不过了解这个技术还是有必要的，所以我决定还是写出来。双缓冲本来是在开发PC应用程序的时候遇到的。在MIDP开发中同样存在，当你在屏幕上进行原始写画的时候，如果很复杂的话，用户会发现界面在闪烁。因此你可以这样做，首先在另一个图片上进行paint()得操作，当完成了以后就把它copy到屏幕上，由于通常copy得时候速度很快就不会出现闪烁了。这个技术就是双缓冲。<span id="more-566"></span></p>
<p>Canvas类提供了isDoubleBuffered()方法来判断设备是不是支持这个功能，如果返回true的话，那么我们就没有必要使用双缓冲了，如果false的话，我们可以这么做：<br />
public DoubleCanvas(UIController uicontroller)<br />
{<br />
super();<br />
this.uicontroller = uicontroller;<br />
width = this.getWidth();<br />
height = this.getHeight();<br />
this.setCommandListener(this);<br />
<span style="background-color: #ff0000;">if(!isDoubleBuffered())<br />
{<br />
offImage = Image.createImage(width,height);<br />
}</span></p>
<p>}<br />
protected void paint(Graphics arg0)<br />
{</p>
<p>arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER|Graphics.TOP);<br />
<span style="background-color: #d3d3d3;"> Graphics saved = arg0;<br />
if(offImage != null)<br />
{<br />
arg0 = offImage.getGraphics();<br />
}<br />
arg0.setColor(255,128,128);<br />
for(int i = 2,j=2;i&lt;width/2-6&amp;&amp;j&lt;height/2-6;i=i+2,j=j+2)<br />
{<br />
arg0.drawRect(i,j,width-2*i,height-2*j);<br />
}<br />
if(arg0 != saved)<br />
{<br />
saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);<br />
}</span></p>
<p><span style="background-color: #d3d3d3;"> }</span></p>
<p><span style="background-color: #ffffff;">得到offImage得Graphics实例后，进行paint()得操作。这个部分通常比较复杂，我这里的不够复杂：）<br />
然后把offImage直接copy到屏幕上也就是执行</span><span style="background-color: #d3d3d3;">saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);<br />
</span></p>
<p><span style="background-color: #d3d3d3;"> <span style="background-color: #ffffff;">我写了一个应用程序来比较使用和不使用双缓冲的效果，但是由于我的手机支持双缓冲所以看不出效果，如果你有兴趣，那么可以把paint()部分的代码修改的复杂一些然后再移植到不支持的手机上也许可以看出效果，下面是我程序的代码：</span></span></p>
<p><span style="background-color: #ffffff;">import javax.microedition.midlet.MIDlet;<br />
import javax.microedition.midlet.MIDletStateChangeException;<br />
</span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
public class <span style="background-color: #ff0000;">DoubleBufferMIDlet </span>extends MIDlet<br />
{<br />
private UIController uicontroller;</p>
<p>protected void startApp() throws MIDletStateChangeException<br />
{<br />
uicontroller = new UIController(this);<br />
uicontroller.init();</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> protected void pauseApp()<br />
{<br />
</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
protected void destroyApp(boolean arg0) throws MIDletStateChangeException<br />
{<br />
</span></span><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">}</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.List;<br />
</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
public class <span style="background-color: #ff0000;">MainListUI</span> extends List implements CommandListener<br />
{</span></span><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
private UIController uicontroller;</p>
<p>public MainListUI(UIController uicontroller)<br />
{<br />
super(&#8220;Test&#8221;,List.IMPLICIT);<br />
this.uicontroller = uicontroller;<br />
this.append(&#8220;Non-buffer&#8221;,null);<br />
this.append(&#8220;Double-buffer&#8221;,null);<br />
this.setCommandListener(this);<br />
}</p>
<p>public void commandAction(Command arg0, Displayable arg1)<br />
{</span></span></p>
<p><span style="background-color: #ffffff;"> if(arg0 == List.SELECT_COMMAND)<br />
{<br />
if(this.getSelectedIndex() == 0)<br />
{</p>
<p>uicontroller.handleEvent(UIController.EventID.DISPLAY_NON_BUFFER);<br />
}<br />
else<br />
{</p>
<p>uicontroller.handleEvent(UIController.EventID.DISPLAY_BUFFER);<br />
}<br />
}<br />
</span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">}<br />
</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;">import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Display;<br />
import javax.microedition.lcdui.Displayable;</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"><br />
public class <span style="background-color: #ff0000;">UIController</span> implements CommandListener<br />
{</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> private Display display;<br />
private DoubleBufferMIDlet midlet;<br />
private MainListUI mainList;<br />
private NonDoubleCanvas noDoubleCanvas;<br />
private DoubleCanvas doubleCanvas;<br />
public static final Command backCommand = new Command(&#8220;Back&#8221;,Command.BACK,2);</p>
<p>public static class EventID<br />
{<br />
public static final int DISPLAY_NON_BUFFER = 0;<br />
public static final int DISPLAY_BUFFER = 1;<br />
}</p>
<p>public UIController(DoubleBufferMIDlet midlet)<br />
{<br />
this.midlet = midlet;<br />
}</p>
<p>public void init()<br />
{<br />
display = Display.getDisplay(midlet);<br />
mainList = new MainListUI(this);<br />
noDoubleCanvas = new NonDoubleCanvas(this);<br />
doubleCanvas = new DoubleCanvas(this);<br />
addCommand();<br />
display.setCurrent(mainList);<br />
}</p>
<p>public void addCommand()<br />
{<br />
noDoubleCanvas.addCommand(backCommand);<br />
doubleCanvas.addCommand(backCommand);<br />
}</p>
<p>public Display getDisplay()<br />
{<br />
return display;<br />
}</p>
<p>public void setCurrent(Displayable disp)<br />
{<br />
display.setCurrent(disp);<br />
}</p>
<p>public void handleEvent(int eventID)<br />
{<br />
switch(eventID)<br />
{<br />
case EventID.DISPLAY_BUFFER:<br />
{<br />
setCurrent(doubleCanvas);<br />
System.out.println(EventID.DISPLAY_BUFFER);<br />
break;<br />
}<br />
case EventID.DISPLAY_NON_BUFFER:<br />
{<br />
setCurrent(noDoubleCanvas);<br />
System.out.println(EventID.DISPLAY_NON_BUFFER);<br />
break;<br />
}<br />
}<br />
}<br />
public void commandAction(Command arg0, Displayable arg1)<br />
{</p>
<p>if(arg0 == backCommand)<br />
{<br />
display.setCurrent(mainList);<br />
}</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> }</span></span></p>
<p><span style="background-color: #d3d3d3;"><span style="background-color: #ffffff;"> </span></span></p>
<p><span style="background-color: #ffffff;">}</span></p>
<p><span style="background-color: #ffffff;">import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.Graphics;</span></p>
<p><span style="background-color: #ffffff;">public class <span style="background-color: #ff0000;">NonDoubleCanvas</span> extends Canvas implements CommandListener<br />
{</p>
<p>private UIController uicontroller;<br />
private int width;<br />
private int height;</p>
<p>public NonDoubleCanvas(UIController uicontroller)<br />
{<br />
super();<br />
this.uicontroller = uicontroller;<br />
width = this.getWidth();<br />
height = this.getHeight();<br />
this.setCommandListener(this);<br />
}</span></p>
<p><span style="background-color: #ffffff;"><br />
protected void paint(Graphics arg0)<br />
{</p>
<p>arg0.setColor(100,100,100);<br />
arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER|Graphics.TOP);<br />
for(int i = 2,j=2;i&lt;width/2-6&amp;&amp;j&lt;height/2-6;i=i+2,j=j+2)<br />
{<br />
arg0.drawRect(i,j,width-2*i,height-2*j);<br />
}</span></p>
<p><span style="background-color: #ffffff;"> }</span></p>
<p><span style="background-color: #ffffff;"> public void commandAction(Command arg0, Displayable arg1)<br />
{</p>
<p>uicontroller.commandAction(arg0,arg1);<br />
}</span></p>
<p><span style="background-color: #ffffff;">}</span></p>
<p><span style="background-color: #ffffff;">import javax.microedition.lcdui.Canvas;<br />
import javax.microedition.lcdui.Command;<br />
import javax.microedition.lcdui.CommandListener;<br />
import javax.microedition.lcdui.Displayable;<br />
import javax.microedition.lcdui.Graphics;<br />
import javax.microedition.lcdui.Image;</span></p>
<p><span style="background-color: #ffffff;">public class <span style="background-color: #ff0000;">DoubleCanvas </span>extends Canvas implements CommandListener<br />
{</span></p>
<p><span style="background-color: #ffffff;"><br />
private UIController uicontroller;<br />
private Image offImage;<br />
private int width;<br />
private int height;</p>
<p>public DoubleCanvas(UIController uicontroller)<br />
{<br />
super();<br />
this.uicontroller = uicontroller;<br />
width = this.getWidth();<br />
height = this.getHeight();<br />
this.setCommandListener(this);<br />
if(!isDoubleBuffered())<br />
{<br />
offImage = Image.createImage(width,height);<br />
}</p>
<p>}</span></p>
<p><span style="background-color: #ffffff;"><br />
protected void paint(Graphics arg0)<br />
{</p>
<p>arg0.drawString(isDoubleBuffered()+&#8221;",width/2,height/2,Graphics.HCENTER|Graphics.TOP);<br />
Graphics saved = arg0;<br />
if(offImage != null)<br />
{<br />
arg0 = offImage.getGraphics();<br />
}<br />
arg0.setColor(255,128,128);<br />
for(int i = 2,j=2;i&lt;width/2-6&amp;&amp;j&lt;height/2-6;i=i+2,j=j+2)<br />
{<br />
arg0.drawRect(i,j,width-2*i,height-2*j);<br />
}<br />
if(arg0 != saved)<br />
{<br />
saved.drawImage(offImage,0,0,Graphics.LEFT|Graphics.TOP);<br />
}</span></p>
<p><span style="background-color: #ffffff;"> }</span></p>
<p><span style="background-color: #ffffff;"> public void commandAction(Command arg0, Displayable arg1)<br />
{<br />
uicontroller.commandAction(arg0,arg1);<br />
}</span></p>
<p><span style="background-color: #ffffff;">}</span></p>
<p><span style="background-color: #ffffff;"> </span></p>
]]></content:encoded>
			<wfw:commentRss>http://www.javagg.com/archives/566/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

